Skip to content

Commit

Permalink
Add Timer.recordNanoseconds Generic Overload (#28) (#30)
Browse files Browse the repository at this point in the history
Motivation:

As discussed in Issue #28, there are a few preferred lightweight APIs for getting timestamps such as `DispatchTime` but those APIs return `UInt64` types, which need to be handled for overflow.

Modifications:

Added a generic `BinaryInteger` overload method for `recordNanoseconds` that guards against accidental overflows from `UInt64` to `Int64`

Result:

Users now have access to a new method to record nanosecond measurements with `Timer` that guards against overflows.
  • Loading branch information
Mordil authored and tomerd committed May 26, 2019
1 parent e4883da commit 8e5110d
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 7 deletions.
9 changes: 9 additions & 0 deletions Sources/CoreMetrics/Metrics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,15 @@ public class Timer {
self.handler.recordNanoseconds(duration)
}

/// Record a duration in nanoseconds.
///
/// - parameters:
/// - value: Duration to record.
@inlinable
public func recordNanoseconds<DataType: BinaryInteger>(_ duration: DataType) {
self.recordNanoseconds(duration >= Int64.max ? Int64.max : Int64(duration))
}

/// Record a duration in microseconds.
///
/// - parameters:
Expand Down
2 changes: 1 addition & 1 deletion Sources/Metrics/Metrics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public extension Timer {
func record(_ duration: DispatchTimeInterval) {
switch duration {
case .nanoseconds(let value):
self.recordNanoseconds(Int64(value))
self.recordNanoseconds(value)
case .microseconds(let value):
self.recordMicroseconds(value)
case .milliseconds(let value):
Expand Down
16 changes: 10 additions & 6 deletions Tests/MetricsTests/CoreMetricsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -224,18 +224,22 @@ class MetricsTests: XCTestCase {
// run the test
let timer = Timer(label: "test-timer")
let testTimer = timer.handler as! TestTimer
// micro
timer.recordMicroseconds(UInt64.max)
// nano
timer.recordNanoseconds(UInt64.max)
XCTAssertEqual(testTimer.values.count, 1, "expected number of entries to match")
XCTAssertEqual(testTimer.values[0].1, Int64.max, "expected value to match")
// milli
timer.recordMilliseconds(UInt64.max)
// micro
timer.recordMicroseconds(UInt64.max)
XCTAssertEqual(testTimer.values.count, 2, "expected number of entries to match")
XCTAssertEqual(testTimer.values[1].1, Int64.max, "expected value to match")
// seconds
timer.recordSeconds(UInt64.max)
// milli
timer.recordMilliseconds(UInt64.max)
XCTAssertEqual(testTimer.values.count, 3, "expected number of entries to match")
XCTAssertEqual(testTimer.values[2].1, Int64.max, "expected value to match")
// seconds
timer.recordSeconds(UInt64.max)
XCTAssertEqual(testTimer.values.count, 4, "expected number of entries to match")
XCTAssertEqual(testTimer.values[3].1, Int64.max, "expected value to match")
}

func testGauge() throws {
Expand Down

0 comments on commit 8e5110d

Please sign in to comment.