4 // Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to deal
8 // in the Software without restriction, including without limitation the rights
9 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 // copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 /// Responsible for computing the timing metrics for the complete lifecycle of a `Request`.
28 public struct Timeline {
29 /// The time the request was initialized.
30 public let requestStartTime: CFAbsoluteTime
32 /// The time the first bytes were received from or sent to the server.
33 public let initialResponseTime: CFAbsoluteTime
35 /// The time when the request was completed.
36 public let requestCompletedTime: CFAbsoluteTime
38 /// The time when the response serialization was completed.
39 public let serializationCompletedTime: CFAbsoluteTime
41 /// The time interval in seconds from the time the request started to the initial response from the server.
42 public let latency: TimeInterval
44 /// The time interval in seconds from the time the request started to the time the request completed.
45 public let requestDuration: TimeInterval
47 /// The time interval in seconds from the time the request completed to the time response serialization completed.
48 public let serializationDuration: TimeInterval
50 /// The time interval in seconds from the time the request started to the time response serialization completed.
51 public let totalDuration: TimeInterval
53 /// Creates a new `Timeline` instance with the specified request times.
55 /// - parameter requestStartTime: The time the request was initialized. Defaults to `0.0`.
56 /// - parameter initialResponseTime: The time the first bytes were received from or sent to the server.
57 /// Defaults to `0.0`.
58 /// - parameter requestCompletedTime: The time when the request was completed. Defaults to `0.0`.
59 /// - parameter serializationCompletedTime: The time when the response serialization was completed. Defaults
62 /// - returns: The new `Timeline` instance.
64 requestStartTime: CFAbsoluteTime = 0.0,
65 initialResponseTime: CFAbsoluteTime = 0.0,
66 requestCompletedTime: CFAbsoluteTime = 0.0,
67 serializationCompletedTime: CFAbsoluteTime = 0.0)
69 self.requestStartTime = requestStartTime
70 self.initialResponseTime = initialResponseTime
71 self.requestCompletedTime = requestCompletedTime
72 self.serializationCompletedTime = serializationCompletedTime
74 self.latency = initialResponseTime - requestStartTime
75 self.requestDuration = requestCompletedTime - requestStartTime
76 self.serializationDuration = serializationCompletedTime - requestCompletedTime
77 self.totalDuration = serializationCompletedTime - requestStartTime
81 // MARK: - CustomStringConvertible
83 extension Timeline: CustomStringConvertible {
84 /// The textual representation used when written to an output stream, which includes the latency, the request
85 /// duration and the total duration.
86 public var description: String {
87 let latency = String(format: "%.3f", self.latency)
88 let requestDuration = String(format: "%.3f", self.requestDuration)
89 let serializationDuration = String(format: "%.3f", self.serializationDuration)
90 let totalDuration = String(format: "%.3f", self.totalDuration)
92 // NOTE: Had to move to string concatenation due to memory leak filed as rdar://26761490. Once memory leak is
93 // fixed, we should move back to string interpolation by reverting commit 7d4a43b1.
95 "\"Latency\": " + latency + " secs",
96 "\"Request Duration\": " + requestDuration + " secs",
97 "\"Serialization Duration\": " + serializationDuration + " secs",
98 "\"Total Duration\": " + totalDuration + " secs"
101 return "Timeline: { " + timings.joined(separator: ", ") + " }"
105 // MARK: - CustomDebugStringConvertible
107 extension Timeline: CustomDebugStringConvertible {
108 /// The textual representation used when written to an output stream, which includes the request start time, the
109 /// initial response time, the request completed time, the serialization completed time, the latency, the request
110 /// duration and the total duration.
111 public var debugDescription: String {
112 let requestStartTime = String(format: "%.3f", self.requestStartTime)
113 let initialResponseTime = String(format: "%.3f", self.initialResponseTime)
114 let requestCompletedTime = String(format: "%.3f", self.requestCompletedTime)
115 let serializationCompletedTime = String(format: "%.3f", self.serializationCompletedTime)
116 let latency = String(format: "%.3f", self.latency)
117 let requestDuration = String(format: "%.3f", self.requestDuration)
118 let serializationDuration = String(format: "%.3f", self.serializationDuration)
119 let totalDuration = String(format: "%.3f", self.totalDuration)
121 // NOTE: Had to move to string concatenation due to memory leak filed as rdar://26761490. Once memory leak is
122 // fixed, we should move back to string interpolation by reverting commit 7d4a43b1.
124 "\"Request Start Time\": " + requestStartTime,
125 "\"Initial Response Time\": " + initialResponseTime,
126 "\"Request Completed Time\": " + requestCompletedTime,
127 "\"Serialization Completed Time\": " + serializationCompletedTime,
128 "\"Latency\": " + latency + " secs",
129 "\"Request Duration\": " + requestDuration + " secs",
130 "\"Serialization Duration\": " + serializationDuration + " secs",
131 "\"Total Duration\": " + totalDuration + " secs"
134 return "Timeline: { " + timings.joined(separator: ", ") + " }"