TimeUnits (#42)
motivation: some metrics backend prefer to be given a hint about the preferred display unit (seconds, milliseconds, etc) to drive the ux changes: add a `preferedUnit` to TimerHandler (and `TimeUnits`) to capture the prefer display unit
This commit is contained in:
parent
853893bbf2
commit
3fefedaaef
|
|
@ -5,3 +5,4 @@
|
|||
.xcode
|
||||
.SourceKitten
|
||||
*.orig
|
||||
.swiftpm
|
||||
|
|
@ -172,6 +172,10 @@ public class Gauge: Recorder {
|
|||
}
|
||||
}
|
||||
|
||||
public enum TimeUnit {
|
||||
case nanoseconds, milliseconds, seconds, minutes, hours, days
|
||||
}
|
||||
|
||||
public extension Timer {
|
||||
/// Create a new `Timer`.
|
||||
///
|
||||
|
|
@ -183,6 +187,18 @@ public extension Timer {
|
|||
self.init(label: label, dimensions: dimensions, handler: handler)
|
||||
}
|
||||
|
||||
/// Create a new `Timer`.
|
||||
///
|
||||
/// - parameters:
|
||||
/// - label: The label for the `Timer`.
|
||||
/// - dimensions: The dimensions for the `Timer`.
|
||||
/// - displayUnit: A hint to the backend responsible for presenting the data of the preferred display unit. This is not guaranteed to be supported by all backends.
|
||||
convenience init(label: String, dimensions: [(String, String)] = [], preferredDisplayUnit displayUnit: TimeUnit) {
|
||||
let handler = MetricsSystem.factory.makeTimer(label: label, dimensions: dimensions)
|
||||
handler.preferDisplayUnit(displayUnit)
|
||||
self.init(label: label, dimensions: dimensions, handler: handler)
|
||||
}
|
||||
|
||||
/// Signal the underlying metrics library that this timer will never be updated again.
|
||||
/// In response the library MAY decide to eagerly release any resources held by this `Timer`.
|
||||
@inlinable
|
||||
|
|
@ -483,6 +499,18 @@ public protocol TimerHandler: AnyObject {
|
|||
/// - parameters:
|
||||
/// - value: Duration to record.
|
||||
func recordNanoseconds(_ duration: Int64)
|
||||
|
||||
/// Set the preferred display unit for this TimerHandler.
|
||||
///
|
||||
/// - parameters:
|
||||
/// - unit: A hint to the backend responsible for presenting the data of the preferred display unit. This is not guaranteed to be supported by all backends.
|
||||
func preferDisplayUnit(_ unit: TimeUnit)
|
||||
}
|
||||
|
||||
extension TimerHandler {
|
||||
public func preferDisplayUnit(_: TimeUnit) {
|
||||
// NOOP
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Predefined Metrics Handlers
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ extension MetricsExtensionsTests {
|
|||
("testTimerBlock", testTimerBlock),
|
||||
("testTimerWithTimeInterval", testTimerWithTimeInterval),
|
||||
("testTimerWithDispatchTime", testTimerWithDispatchTime),
|
||||
("testTimerUnits", testTimerUnits),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,32 @@ class MetricsExtensionsTests: XCTestCase {
|
|||
XCTAssertEqual(testTimer.values.count, 5, "expected number of entries to match")
|
||||
XCTAssertEqual(testTimer.values[4].1, 0, "expected value to match")
|
||||
}
|
||||
|
||||
func testTimerUnits() throws {
|
||||
let metrics = TestMetrics()
|
||||
MetricsSystem.bootstrapInternal(metrics)
|
||||
|
||||
let name = "timer-\(NSUUID().uuidString)"
|
||||
let value = Int64.random(in: 0 ... 1000)
|
||||
|
||||
let timer = Timer(label: name)
|
||||
timer.recordNanoseconds(value)
|
||||
|
||||
let testTimer = timer.handler as! TestTimer
|
||||
XCTAssertEqual(testTimer.values.count, 1, "expected number of entries to match")
|
||||
XCTAssertEqual(testTimer.values.first!.1, value, "expected value to match")
|
||||
XCTAssertEqual(metrics.timers.count, 1, "timer should have been stored")
|
||||
|
||||
let secondsName = "timer-seconds-\(NSUUID().uuidString)"
|
||||
let secondsValue = Int64.random(in: 0 ... 1000)
|
||||
let secondsTimer = Timer(label: secondsName, preferredDisplayUnit: .seconds)
|
||||
secondsTimer.recordSeconds(secondsValue)
|
||||
|
||||
let testSecondsTimer = secondsTimer.handler as! TestTimer
|
||||
XCTAssertEqual(testSecondsTimer.values.count, 1, "expected number of entries to match")
|
||||
XCTAssertEqual(testSecondsTimer.retriveValueInPreferredUnit(atIndex: 0), secondsValue, "expected value to match")
|
||||
XCTAssertEqual(metrics.timers.count, 2, "timer should have been stored")
|
||||
}
|
||||
}
|
||||
|
||||
// https://bugs.swift.org/browse/SR-6310
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ internal class TestRecorder: RecorderHandler, Equatable {
|
|||
internal class TestTimer: TimerHandler, Equatable {
|
||||
let id: String
|
||||
let label: String
|
||||
var displayUnit: TimeUnit?
|
||||
let dimensions: [(String, String)]
|
||||
|
||||
let lock = NSLock()
|
||||
|
|
@ -143,9 +144,33 @@ internal class TestTimer: TimerHandler, Equatable {
|
|||
init(label: String, dimensions: [(String, String)]) {
|
||||
self.id = NSUUID().uuidString
|
||||
self.label = label
|
||||
self.displayUnit = nil
|
||||
self.dimensions = dimensions
|
||||
}
|
||||
|
||||
func preferDisplayUnit(_ unit: TimeUnit) {
|
||||
self.lock.withLock {
|
||||
self.displayUnit = unit
|
||||
}
|
||||
}
|
||||
|
||||
func retriveValueInPreferredUnit(atIndex i: Int) -> Int64 {
|
||||
return self.lock.withLock {
|
||||
let value = values[i].1
|
||||
guard let displayUnit = self.displayUnit else {
|
||||
return value
|
||||
}
|
||||
switch displayUnit {
|
||||
case .days: return (value / 1_000_000_000) * 60 * 60 * 24
|
||||
case .hours: return (value / 1_000_000_000) * 60 * 60
|
||||
case .minutes: return (value / 1_000_000_000) * 60
|
||||
case .seconds: return value / 1_000_000_000
|
||||
case .milliseconds: return value / 1_000_000
|
||||
case .nanoseconds: return value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func recordNanoseconds(_ duration: Int64) {
|
||||
self.lock.withLock {
|
||||
values.append((Date(), duration))
|
||||
|
|
|
|||
Loading…
Reference in New Issue