Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Network traffic statistics changes #143

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions Sources/CustomHTTPProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,6 @@ public class CustomHTTPProtocol: URLProtocol {
override public func stopLoading() {
sessionTask?.cancel()
currentRequest?.httpBody = body(from: request)
if let startDate = currentRequest?.date{
currentRequest?.duration = fabs(startDate.timeIntervalSinceNow) * 1000 //Find elapsed time and convert to milliseconds
}

Storage.shared.saveRequest(request: currentRequest)
session?.invalidateAndCancel()
}
Expand Down Expand Up @@ -138,6 +134,23 @@ extension CustomHTTPProtocol: URLSessionDataDelegate {
public func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
client?.urlProtocolDidFinishLoading(self)
}

public func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
currentRequest?.startDate = metrics.taskInterval.start
currentRequest?.requestStartDate = metrics.transactionMetrics.first?.requestStartDate
currentRequest?.requestEndDate = metrics.transactionMetrics.first?.requestEndDate
currentRequest?.responseStartDate = metrics.transactionMetrics.first?.responseStartDate
currentRequest?.responseEndDate = metrics.transactionMetrics.first?.responseEndDate
currentRequest?.duration = Double(metrics.taskInterval.duration) * 1000
if #available(iOS 13.0, *) {
currentRequest?.countOfRequestBodyBytesBeforeEncoding = metrics.transactionMetrics.first?.countOfRequestBodyBytesBeforeEncoding
currentRequest?.countOfRequestBodyBytesSent = metrics.transactionMetrics.first?.countOfRequestBodyBytesSent
currentRequest?.countOfRequestHeaderBytesSent = metrics.transactionMetrics.first?.countOfRequestHeaderBytesSent
currentRequest?.countOfResponseBodyBytesAfterDecoding = metrics.transactionMetrics.first?.countOfResponseBodyBytesAfterDecoding
currentRequest?.countOfResponseBodyBytesReceived = metrics.transactionMetrics.first?.countOfResponseBodyBytesReceived
currentRequest?.countOfResponseHeaderBytesReceived = metrics.transactionMetrics.first?.countOfResponseHeaderBytesReceived
}
}
}

final class CustomAuthenticationChallengeSender: NSObject, URLAuthenticationChallengeSender {
Expand Down
90 changes: 84 additions & 6 deletions Sources/Models/RequestModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ open class RequestModel: Codable {
public let host: String?
public let port: Int?
public let scheme: String?
public let date: Date
public let method: String
public let headers: [String: String]
public var credentials: [String : String]
Expand All @@ -25,14 +24,25 @@ open class RequestModel: Codable {
open var dataResponse: Data?
open var errorClientDescription: String?
open var duration: Double?


public var startDate: Date?
public var requestStartDate: Date?
public var requestEndDate: Date?
public var responseStartDate: Date?
public var responseEndDate: Date?
public var countOfRequestBodyBytesBeforeEncoding: Int64?
public var countOfRequestBodyBytesSent: Int64?
public var countOfRequestHeaderBytesSent: Int64?
public var countOfResponseBodyBytesAfterDecoding: Int64?
public var countOfResponseBodyBytesReceived: Int64?
public var countOfResponseHeaderBytesReceived: Int64?

init(request: NSURLRequest, session: URLSession?) {
id = UUID().uuidString
url = request.url?.absoluteString ?? ""
host = request.url?.host
port = request.url?.port
scheme = request.url?.scheme
date = Date()
method = request.httpMethod ?? "GET"
credentials = [:]
var headers = request.allHTTPHeaderFields ?? [:]
Expand Down Expand Up @@ -135,14 +145,15 @@ open class RequestModel: Codable {
guard
let url = URL(string: self.url),
let scheme = self.scheme,
let host = self.host
let host = self.host,
let startDate = self.startDate
else { return nil }

let dateFormatterGet = DateFormatter()
dateFormatterGet.dateFormat = "yyyyMMdd_HHmmss"

let name = "\(dateFormatterGet.string(from: date))-\(url)"
let name = "\(dateFormatterGet.string(from: startDate))-\(url)"

var headers: [PMHeader] = []
let method = self.method
for header in self.headers {
Expand Down Expand Up @@ -191,4 +202,71 @@ open class RequestModel: Codable {

return PMItem(name: name, item: nil, request: request, response: [response])
}

var preRequestTime: Double? {
guard let requestStartDate = self.requestStartDate,
let startDate = self.startDate else { return nil }
return requestStartDate.durationInMilliSeconds(since: startDate)
}

var requestTime: Double? {
guard let requestEndDate = self.requestEndDate,
let requestStartDate = self.requestStartDate else { return nil }
return requestEndDate.durationInMilliSeconds(since: requestStartDate)
}

var responseTime: Double? {
guard let responseStartDate = self.responseStartDate,
let requestEndDate = self.requestEndDate else { return nil }
return responseStartDate.durationInMilliSeconds(since: requestEndDate)
}

var downloadTime: Double? {
guard let responseEndDate = self.responseEndDate,
let responseStartDate = self.responseStartDate else { return nil }
return responseEndDate.durationInMilliSeconds(since: responseStartDate)
}
}


extension Date {
func durationInMilliSeconds() -> Double {
let double = Date().timeIntervalSince(self) * 1000
return double.round(to: 3)
}

func durationInMilliSeconds(since date: Date) -> Double {
let double = self.timeIntervalSince(date) * 1000
return double.round(to: 3)
}
}


extension Double {
func round(to places: Int) -> Double {
let divisor = pow(10.0, Double(places))
return (self * divisor).rounded() / divisor
}
}


extension Int64 {
var kilobytes: Double { return Double(self) / 1_024 }
var megabytes: Double { return kilobytes / 1_024 }
var gigabytes: Double { return megabytes / 1_024 }

public func getReadableUnit() -> String {
switch self {
case 0..<1_024:
return "\(self) bytes"
case 1_024..<(1_024 * 1_024):
return "\(String(format: "%.2f", kilobytes)) kb"
case 1_024..<(1_024 * 1_024 * 1_024):
return "\(String(format: "%.2f", megabytes)) mb"
case (1_024 * 1_024 * 1_024)...Int64.max:
return "\(String(format: "%.2f", gigabytes)) gb"
default:
return "\(self) bytes"
}
}
}
23 changes: 20 additions & 3 deletions Sources/Utils/RequestModelBeautifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,27 @@ class RequestModelBeautifier: NSObject {
let url = NSMutableAttributedString().bold("URL ").normal(request.url + "\n")
let method = NSMutableAttributedString().bold("Method ").normal(request.method + "\n")
let responseCode = NSMutableAttributedString().bold("Response Code ").normal((request.code != 0 ? "\(request.code)" : "-") + "\n")
let requestStartTime = NSMutableAttributedString().bold("Request Start Time ").normal((request.date.stringWithFormat(dateFormat: "MMM d yyyy - HH:mm:ss") ?? "-") + "\n")
let duration = NSMutableAttributedString().bold("Duration ").normal(request.duration?.formattedMilliseconds() ?? "-" + "\n")
let requestStartTime = NSMutableAttributedString().bold("Request Start Time ").normal((request.startDate?.stringWithFormat(dateFormat: "MMM d yyyy - HH:mm:ss") ?? "-") + "\n")

let preRequestTime = NSMutableAttributedString().bold("Pre-Request Duration ").normal((request.preRequestTime?.formattedMilliseconds() ?? "-") + "\n")
let requestTime = NSMutableAttributedString().bold("Request Duration ").normal((request.requestTime?.formattedMilliseconds() ?? "-") + "\n")
let responseTime = NSMutableAttributedString().bold("Response Duration ").normal((request.responseTime?.formattedMilliseconds() ?? "-") + "\n")
let downloadTime = NSMutableAttributedString().bold("Download Duration ").normal((request.downloadTime?.formattedMilliseconds() ?? "-") + "\n")
let duration = NSMutableAttributedString().bold("Total Duration ").normal(request.duration?.formattedMilliseconds() ?? "-")

let final = NSMutableAttributedString()
for attr in [url, method, responseCode, requestStartTime, duration]{
var items: [NSMutableAttributedString] = []
if #available(iOS 13.0, *) {
let requestBodyBytesSent = NSMutableAttributedString().bold("Request Body Bytes Sent ").normal((request.countOfRequestBodyBytesSent?.getReadableUnit() ?? "-") + "\n")
let requestHeaderBytesSent = NSMutableAttributedString().bold("Request Header Bytes Sent ").normal((request.countOfRequestHeaderBytesSent?.getReadableUnit() ?? "-") + "\n")
let responseBodyBytesReceived = NSMutableAttributedString().bold("Response Body Bytes Received ").normal((request.countOfResponseBodyBytesReceived?.getReadableUnit() ?? "-") + "\n")
let responseHeaderBytesReceived = NSMutableAttributedString().bold("Response Header Bytes Received ").normal((request.countOfResponseHeaderBytesReceived?.getReadableUnit() ?? "-") + "\n")
items = [url, method, responseCode, requestStartTime, requestBodyBytesSent, requestHeaderBytesSent, responseBodyBytesReceived, responseHeaderBytesReceived, preRequestTime, requestTime, responseTime, downloadTime, duration]
} else {
items = [url, method, responseCode, requestStartTime, preRequestTime, requestTime, responseTime, downloadTime, duration]
}

for attr in items {
final.append(attr)
}
return final
Expand Down