Skip to content

Commit c285c96

Browse files
authored
Merge pull request #2888 from jshier/add-urlsessiontask-metrics-5.3
[5.3] Add URLSessionTaskMetrics
2 parents e13f3ad + e52bb0e commit c285c96

File tree

4 files changed

+151
-13
lines changed

4 files changed

+151
-13
lines changed

Foundation.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
231503DB1D8AEE5D0061694D /* TestDecimal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 231503DA1D8AEE5D0061694D /* TestDecimal.swift */; };
8080
294E3C1D1CC5E19300E4F44C /* TestNSAttributedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 294E3C1C1CC5E19300E4F44C /* TestNSAttributedString.swift */; };
8181
2EBE67A51C77BF0E006583D5 /* TestDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EBE67A31C77BF05006583D5 /* TestDateFormatter.swift */; };
82+
316577C425214A8400492943 /* URLSessionTaskMetrics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 316577C325214A8400492943 /* URLSessionTaskMetrics.swift */; };
8283
3E55A2331F52463B00082000 /* TestUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E55A2321F52463B00082000 /* TestUnit.swift */; };
8384
3EA9D6701EF0532D00B362D6 /* TestJSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA9D66F1EF0532D00B362D6 /* TestJSONEncoder.swift */; };
8485
3EDCE50C1EF04D8100C2EC04 /* Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EDCE5051EF04D8100C2EC04 /* Codable.swift */; };
@@ -787,6 +788,7 @@
787788
231503DA1D8AEE5D0061694D /* TestDecimal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestDecimal.swift; sourceTree = "<group>"; };
788789
294E3C1C1CC5E19300E4F44C /* TestNSAttributedString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSAttributedString.swift; sourceTree = "<group>"; };
789790
2EBE67A31C77BF05006583D5 /* TestDateFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestDateFormatter.swift; sourceTree = "<group>"; };
791+
316577C325214A8400492943 /* URLSessionTaskMetrics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = URLSessionTaskMetrics.swift; path = URLSession/URLSessionTaskMetrics.swift; sourceTree = "<group>"; };
790792
3E55A2321F52463B00082000 /* TestUnit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestUnit.swift; sourceTree = "<group>"; };
791793
3EA9D66F1EF0532D00B362D6 /* TestJSONEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestJSONEncoder.swift; sourceTree = "<group>"; };
792794
3EDCE5051EF04D8100C2EC04 /* Codable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Codable.swift; sourceTree = "<group>"; };
@@ -2184,6 +2186,7 @@
21842186
F023075823F0B7AC0023DBEC /* URLSessionConfiguration.swift */,
21852187
F023075623F0B7AC0023DBEC /* URLSessionDelegate.swift */,
21862188
F023075B23F0B7AD0023DBEC /* URLSessionTask.swift */,
2189+
316577C325214A8400492943 /* URLSessionTaskMetrics.swift */,
21872190
);
21882191
name = URLSession;
21892192
sourceTree = "<group>";
@@ -2786,6 +2789,7 @@
27862789
F023076823F0B8740023DBEC /* Boxing.swift in Sources */,
27872790
F023073123F0B6E20023DBEC /* BodySource.swift in Sources */,
27882791
F023075E23F0B7AD0023DBEC /* NetworkingSpecific.swift in Sources */,
2792+
316577C425214A8400492943 /* URLSessionTaskMetrics.swift in Sources */,
27892793
F023073423F0B6F10023DBEC /* FTPURLProtocol.swift in Sources */,
27902794
F023073E23F0B7100023DBEC /* MultiHandle.swift in Sources */,
27912795
15B803E6228F376000B30FF6 /* NSURLRequest.swift in Sources */,

Sources/FoundationNetworking/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ add_library(FoundationNetworking
4343
URLSession/URLSessionConfiguration.swift
4444
URLSession/URLSessionDelegate.swift
4545
URLSession/URLSessionTask.swift
46+
URLSession/URLSessionTaskMetrics.swift
4647
URLSession/libcurl/EasyHandle.swift
4748
URLSession/libcurl/MultiHandle.swift
4849
URLSession/libcurl/libcurlHelpers.swift)

Sources/FoundationNetworking/URLSession/URLSessionDelegate.swift

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public protocol URLSessionDelegate : NSObjectProtocol {
7171
* behavior will be to use the default handling, which may involve user
7272
* interaction.
7373
*/
74-
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
74+
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
7575
}
7676

7777
extension URLSessionDelegate {
@@ -115,19 +115,21 @@ public protocol URLSessionTaskDelegate : URLSessionDelegate {
115115
* necessary when authentication has failed for any request that
116116
* involves a body stream.
117117
*/
118-
func urlSession(_ session: URLSession, task: URLSessionTask, needNewBodyStream completionHandler: @escaping (InputStream?) -> Void)
118+
func urlSession(_ session: URLSession, task: URLSessionTask, needNewBodyStream completionHandler: @escaping (InputStream?) -> Void)
119119

120120
/* Sent periodically to notify the delegate of upload progress. This
121121
* information is also available as properties of the task.
122122
*/
123-
func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64)
123+
func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64)
124124

125125
/* Sent as the last message related to a specific task. Error may be
126126
* nil, which implies that no error occurred and this task is complete.
127127
*/
128-
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
128+
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
129129

130-
func urlSession(_ session: URLSession, task: URLSessionTask, willBeginDelayedRequest request: URLRequest, completionHandler: @escaping (URLSession.DelayedRequestDisposition, URLRequest?) -> Void)
130+
func urlSession(_ session: URLSession, task: URLSessionTask, willBeginDelayedRequest request: URLRequest, completionHandler: @escaping (URLSession.DelayedRequestDisposition, URLRequest?) -> Void)
131+
132+
func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics)
131133
}
132134

133135
extension URLSessionTaskDelegate {
@@ -148,6 +150,8 @@ extension URLSessionTaskDelegate {
148150
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { }
149151

150152
public func urlSession(_ session: URLSession, task: URLSessionTask, willBeginDelayedRequest request: URLRequest, completionHandler: @escaping (URLSession.DelayedRequestDisposition, URLRequest?) -> Void) { }
153+
154+
public func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) { }
151155
}
152156

153157
/*
@@ -204,7 +208,7 @@ public protocol URLSessionDataDelegate : URLSessionTaskDelegate {
204208
* attempted for a given resource, and you should not rely on this
205209
* message to receive the resource data.
206210
*/
207-
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse, completionHandler: @escaping (CachedURLResponse?) -> Void)
211+
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse, completionHandler: @escaping (CachedURLResponse?) -> Void)
208212

209213
}
210214

@@ -232,17 +236,17 @@ public protocol URLSessionDownloadDelegate : URLSessionTaskDelegate {
232236
* removed when the delegate message returns. URLSession:task:didCompleteWithError: will
233237
* still be called.
234238
*/
235-
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)
239+
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)
236240

237241
/* Sent periodically to notify the delegate of download progress. */
238-
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)
242+
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)
239243

240244
/* Sent when a download has been resumed. If a download failed with an
241245
* error, the -userInfo dictionary of the error will contain an
242246
* URLSessionDownloadTaskResumeData key, whose value is the resume
243247
* data.
244248
*/
245-
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64)
249+
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64)
246250
}
247251

248252
extension URLSessionDownloadDelegate {
@@ -259,13 +263,13 @@ public protocol URLSessionStreamDelegate : URLSessionTaskDelegate {
259263
* this delegate message is received, there may still be bytes
260264
* available. You only know that no more bytes are available when you
261265
* are able to read until EOF. */
262-
func urlSession(_ session: URLSession, readClosedFor streamTask: URLSessionStreamTask)
266+
func urlSession(_ session: URLSession, readClosedFor streamTask: URLSessionStreamTask)
263267

264268
/* Indicates that the write side of a connection has been closed.
265269
* Any outstanding writes complete, but future writes will immediately
266270
* fail.
267271
*/
268-
func urlSession(_ session: URLSession, writeClosedFor streamTask: URLSessionStreamTask)
272+
func urlSession(_ session: URLSession, writeClosedFor streamTask: URLSessionStreamTask)
269273

270274
/* A notification that the system has determined that a better route
271275
* to the host has been detected (eg, a wi-fi interface becoming
@@ -274,15 +278,15 @@ public protocol URLSessionStreamDelegate : URLSessionTaskDelegate {
274278
* there is no guarantee that the future task will be able to connect
275279
* to the host, so callers should should be prepared for failure of
276280
* reads and writes over any new interface. */
277-
func urlSession(_ session: URLSession, betterRouteDiscoveredFor streamTask: URLSessionStreamTask)
281+
func urlSession(_ session: URLSession, betterRouteDiscoveredFor streamTask: URLSessionStreamTask)
278282

279283
/* The given task has been completed, and unopened InputStream and
280284
* OutputStream objects are created from the underlying network
281285
* connection. This will only be invoked after all enqueued IO has
282286
* completed (including any necessary handshakes.) The streamTask
283287
* will not receive any further delegate messages.
284288
*/
285-
func urlSession(_ session: URLSession, streamTask: URLSessionStreamTask, didBecome inputStream: InputStream, outputStream: OutputStream)
289+
func urlSession(_ session: URLSession, streamTask: URLSessionStreamTask, didBecome inputStream: InputStream, outputStream: OutputStream)
286290
}
287291

288292
extension URLSessionStreamDelegate {
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// Foundation/URLSession/URLSessionTaskMetrics.swift - URLSession API
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
// -----------------------------------------------------------------------------
12+
///
13+
/// URLSession API code.
14+
/// - SeeAlso: URLSession.swift
15+
///
16+
// -----------------------------------------------------------------------------
17+
18+
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
19+
import SwiftFoundation
20+
#else
21+
import Foundation
22+
#endif
23+
@_implementationOnly import CoreFoundation
24+
25+
open class URLSessionTaskMetrics : NSObject {
26+
public internal(set) var transactionMetrics: [URLSessionTaskTransactionMetrics] = []
27+
public internal(set) var taskInterval: DateInterval = .init()
28+
public internal(set) var redirectCount = 0
29+
30+
public enum ResourceFetchType: Int {
31+
case unknown = 0
32+
case networkLoad = 1
33+
case serverPush = 2
34+
case localCache = 3
35+
}
36+
37+
public enum DomainResolutionProtocol: Int {
38+
case unknown = 0
39+
case udp = 1
40+
case tcp = 2
41+
case tls = 3
42+
case https = 4
43+
}
44+
}
45+
46+
open class URLSessionTaskTransactionMetrics: NSObject {
47+
public let request: URLRequest
48+
public internal(set) var response: URLResponse?
49+
50+
public internal(set) var fetchStartDate: Date?
51+
public internal(set) var domainLookupStartDate: Date?
52+
public internal(set) var domainLookupEndDate: Date?
53+
public internal(set) var connectStartDate: Date?
54+
public internal(set) var secureConnectionStartDate: Date?
55+
public internal(set) var secureConnectionEndDate: Date?
56+
public internal(set) var connectEndDate: Date?
57+
public internal(set) var requestStartDate: Date?
58+
public internal(set) var requestEndDate: Date?
59+
public internal(set) var responseStartDate: Date?
60+
public internal(set) var responseEndDate: Date?
61+
62+
public internal(set) var countOfRequestBodyBytesBeforeEncoding: Int64 = 0
63+
public internal(set) var countOfRequestBodyBytesSent: Int64 = 0
64+
public internal(set) var countOfRequestHeaderBytesSent: Int64 = 0
65+
public internal(set) var countOfResponseBodyBytesAfterDecoding: Int64 = 0
66+
public internal(set) var countOfResponseBodyBytesReceived: Int64 = 0
67+
public internal(set) var countOfResponseHeaderBytesReceived: Int64 = 0
68+
69+
public internal(set) var networkProtocolName: String?
70+
public internal(set) var remoteAddress: String?
71+
public internal(set) var remotePort: String?
72+
public internal(set) var localAddress: String?
73+
public internal(set) var localPort: String?
74+
public internal(set) var negotiatedTLSCipherSuite: tls_ciphersuite_t?
75+
public internal(set) var negotiatedTLSProtocolVersion: tls_protocol_version_t?
76+
public internal(set) var isCellular: Bool = false
77+
public internal(set) var isExpensive: Bool = false
78+
public internal(set) var isConstrained: Bool = false
79+
public internal(set) var isProxyConnection: Bool = false
80+
public internal(set) var isReusedConnection: Bool = false
81+
public internal(set) var isMultipath: Bool = false
82+
public internal(set) var resourceFetchType: URLSessionTaskMetrics.ResourceFetchType = .unknown
83+
public internal(set) var domainResolutionProtocol: URLSessionTaskMetrics.DomainResolutionProtocol = .unknown
84+
85+
init(request: URLRequest) {
86+
self.request = request
87+
}
88+
}
89+
90+
public enum tls_ciphersuite_t: UInt16 {
91+
case AES_128_GCM_SHA256 = 4865
92+
case AES_256_GCM_SHA384 = 4866
93+
94+
case CHACHA20_POLY1305_SHA256 = 4867
95+
96+
case ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 49160
97+
case ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 49161
98+
case ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 49187
99+
case ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 49195
100+
case ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 49162
101+
case ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 49188
102+
case ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 49196
103+
case ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 52393
104+
case ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 49170
105+
case ECDHE_RSA_WITH_AES_128_CBC_SHA = 49171
106+
case ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 49191
107+
case ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 49199
108+
case ECDHE_RSA_WITH_AES_256_CBC_SHA = 49172
109+
case ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 49192
110+
case ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 49200
111+
case ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 52392
112+
113+
case RSA_WITH_3DES_EDE_CBC_SHA = 10
114+
case RSA_WITH_AES_128_CBC_SHA = 47
115+
case RSA_WITH_AES_128_CBC_SHA256 = 60
116+
case RSA_WITH_AES_128_GCM_SHA256 = 156
117+
case RSA_WITH_AES_256_CBC_SHA = 53
118+
case RSA_WITH_AES_256_CBC_SHA256 = 61
119+
case RSA_WITH_AES_256_GCM_SHA384 = 157
120+
}
121+
122+
public enum tls_protocol_version_t: UInt16 {
123+
case TLSv10 = 769
124+
case TLSv11 = 770
125+
case TLSv12 = 771
126+
case TLSv13 = 772
127+
case DTLSv10 = 65279
128+
case DTLSv12 = 65277
129+
}

0 commit comments

Comments
 (0)