swift-metrics/Tests/MetricsTests/TestMetrics.swift

129 lines
3.8 KiB
Swift

@testable import CoreMetrics
@testable import protocol CoreMetrics.Timer
import Foundation
internal class TestMetrics: MetricsHandler {
private let lock = NSLock() // TODO: consider lock per cache?
var counters = [Counter]()
var recorders = [Recorder]()
var timers = [Timer]()
public func makeCounter(label: String, dimensions: [(String, String)]) -> Counter {
return self.make(label: label, dimensions: dimensions, registry: &self.counters, maker: TestCounter.init)
}
public func makeRecorder(label: String, dimensions: [(String, String)], aggregate: Bool) -> Recorder {
let maker = { (label: String, dimensions: [(String, String)]) -> Recorder in
TestRecorder(label: label, dimensions: dimensions, aggregate: aggregate)
}
return self.make(label: label, dimensions: dimensions, registry: &self.recorders, maker: maker)
}
public func makeTimer(label: String, dimensions: [(String, String)]) -> Timer {
return self.make(label: label, dimensions: dimensions, registry: &self.timers, maker: TestTimer.init)
}
private func make<Item>(label: String, dimensions: [(String, String)], registry: inout [Item], maker: (String, [(String, String)]) -> Item) -> Item {
let item = maker(label, dimensions)
return self.lock.withLock {
registry.append(item)
return item
}
}
}
internal class TestCounter: Counter, Equatable {
let id: String
let label: String
let dimensions: [(String, String)]
let lock = NSLock()
var values = [(Date, Int64)]()
init(label: String, dimensions: [(String, String)]) {
self.id = NSUUID().uuidString
self.label = label
self.dimensions = dimensions
}
func increment<DataType: BinaryInteger>(_ value: DataType) {
self.lock.withLock {
self.values.append((Date(), Int64(value)))
}
print("adding \(value) to \(self.label)")
}
public static func == (lhs: TestCounter, rhs: TestCounter) -> Bool {
return lhs.id == rhs.id
}
}
internal class TestRecorder: Recorder, Equatable {
let id: String
let label: String
let dimensions: [(String, String)]
let aggregate: Bool
let lock = NSLock()
var values = [(Date, Double)]()
init(label: String, dimensions: [(String, String)], aggregate: Bool) {
self.id = NSUUID().uuidString
self.label = label
self.dimensions = dimensions
self.aggregate = aggregate
}
func record<DataType: BinaryInteger>(_ value: DataType) {
self.record(Double(value))
}
func record<DataType: BinaryFloatingPoint>(_ value: DataType) {
self.lock.withLock {
// this may loose percision but good enough as an example
values.append((Date(), Double(value)))
}
print("recoding \(value) in \(self.label)")
}
public static func == (lhs: TestRecorder, rhs: TestRecorder) -> Bool {
return lhs.id == rhs.id
}
}
internal class TestTimer: Timer, Equatable {
let id: String
let label: String
let dimensions: [(String, String)]
let lock = NSLock()
var values = [(Date, Int64)]()
init(label: String, dimensions: [(String, String)]) {
self.id = NSUUID().uuidString
self.label = label
self.dimensions = dimensions
}
func recordNanoseconds(_ duration: Int64) {
self.lock.withLock {
values.append((Date(), duration))
}
print("recoding \(duration) \(self.label)")
}
public static func == (lhs: TestTimer, rhs: TestTimer) -> Bool {
return lhs.id == rhs.id
}
}
private extension NSLock {
func withLock<T>(_ body: () -> T) -> T {
self.lock()
defer {
self.unlock()
}
return body()
}
}