Closed ktoso closed 4 years ago
extension SWIM {
public struct Metrics {
/// Number of members (total)
let members: Gauge
/// Number of members (alive)
let membersAlive: Gauge
/// Number of members (suspect)
let membersSuspect: Gauge
/// Number of members (unreachable)
let membersUnreachable: Gauge
/// Number of members (dead)
let membersDead: Gauge
/// Records time it takes for ping round-trips
let pingResponseTime: Timer
/// Records time it takes for (every) pingRequest round-trip
let pingRequestResponseTimeAll: Timer
let pingRequestResponseTimeFirst: Timer
/// Records the incarnation of the SWIM instance.
///
/// Incarnation numbers are bumped whenever the node needs to refute some gossip about itself,
/// as such the incarnation number *growth* is an interesting indicator of cluster observation churn.
let incarnation: Gauge
let successfulProbeCount: Gauge
let failedProbeCount: Gauge
// TODO: message sizes (count and bytes)
init(settings: SWIM.Settings) {
self.members = Gauge(
label: settings.metrics.makeLabel("members"),
dimensions: [("status", "all")]
)
self.membersAlive = Gauge(
label: settings.metrics.makeLabel("members"),
dimensions: [("status", "alive")]
)
self.membersSuspect = Gauge(
label: settings.metrics.makeLabel("members"),
dimensions: [("status", "dead")]
)
self.membersUnreachable = Gauge(
label: settings.metrics.makeLabel("members"),
dimensions: [("status", "unreachable")]
)
self.membersDead = Gauge(
label: settings.metrics.makeLabel("members"),
dimensions: [("status", "dead")]
)
self.pingResponseTime = Timer(label: settings.metrics.makeLabel("responseRoundTrip", "ping"))
self.pingRequestResponseTimeAll = Timer(
label: settings.metrics.makeLabel("responseRoundTrip", "pingRequest"),
dimensions: [("type", "all")]
)
self.pingRequestResponseTimeFirst = Timer(
label: settings.metrics.makeLabel("responseRoundTrip", "pingRequest"),
dimensions: [("type", "firstSuccessful")]
)
self.incarnation = Gauge(label: settings.metrics.makeLabel("incarnation"))
self.successfulProbeCount = Gauge(
label: settings.metrics.makeLabel("incarnation"),
dimensions: [("type", "successful")]
)
self.failedProbeCount = Gauge(
label: settings.metrics.makeLabel("incarnation"),
dimensions: [("type", "failed")]
)
}
}
}
// ==== ----------------------------------------------------------------------------------------------------------------
// MARK: SWIM Metrics Settings
/// Configure label names and other details about metrics reported by the `SWIM.Instance`.
public struct SWIMMetricsSettings {
public init() {}
/// Configure the segments separator for use when creating labels;
/// Some systems like graphite like "." as the separator, yet others may not treat this as legal character.
///
/// Typical alternative values are "/" or "_", though consult your metrics backend before changing this setting.
public var segmentSeparator: String = "."
/// Prefix all metrics with this segment.
///
/// If set, this is used as the first part of a label name, followed by `labelPrefix`.
public var systemName: String?
/// Label string prefixed before all emitted metrics names in their labels.
///
/// - SeeAlso: `systemName`, if set, is prefixed before `labelPrefix` when creating label names.
public var labelPrefix: String? = "swim"
func makeLabel(_ segments: String...) -> String {
let systemNamePart: String = self.systemName.map { "\($0)\(self.segmentSeparator)" } ?? ""
let systemMetricsPrefixPart: String = self.labelPrefix.map { "\($0)\(self.segmentSeparator)" } ?? ""
let joinedSegments = segments.joined(separator: self.segmentSeparator)
return "\(systemNamePart)\(systemMetricsPrefixPart)\(joinedSegments)"
}
}
and insert those at the right spots
build in some metrics, probably right away into the instance.