mirror of
https://github.com/swift-server/swift-prometheus.git
synced 2026-05-03 07:32:27 +00:00
Switch from swiftformat to swift-format (#107)
* Switch from swiftformat to swift-format * Format Tests according to swift-format * Apply same .swift-format as apple/swift-certificates * Fix docker/docker-compose.2204.59.yaml to be like other Dockerfiles * Update default Swift version to 5.8 in Dockerfile As of Swift 5.8, swift-format depends on the version of SwiftSyntax whose parser has been rewritten in Swift and no longer has dependencies on libraries in the Swift toolchain. Defaulting to Swift 5.8 fixes the usage of swift-format in nightly builds. * Fix Dockerfile to have swift-format accessible
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"fileScopedDeclarationPrivacy": {
|
||||
"accessLevel": "private"
|
||||
},
|
||||
"indentation": {
|
||||
"spaces": 4
|
||||
},
|
||||
"indentConditionalCompilationBlocks": false,
|
||||
"indentSwitchCaseLabels": false,
|
||||
"lineBreakAroundMultilineExpressionChainComponents": false,
|
||||
"lineBreakBeforeControlFlowKeywords": false,
|
||||
"lineBreakBeforeEachArgument": true,
|
||||
"lineBreakBeforeEachGenericRequirement": true,
|
||||
"lineLength": 120,
|
||||
"maximumBlankLines": 1,
|
||||
"prioritizeKeepingFunctionOutputTogether": true,
|
||||
"respectsExistingLineBreaks": true,
|
||||
"rules": {
|
||||
"AllPublicDeclarationsHaveDocumentation": false,
|
||||
"AlwaysUseLowerCamelCase": false,
|
||||
"AmbiguousTrailingClosureOverload": true,
|
||||
"BeginDocumentationCommentWithOneLineSummary": false,
|
||||
"DoNotUseSemicolons": true,
|
||||
"DontRepeatTypeInStaticProperties": true,
|
||||
"FileScopedDeclarationPrivacy": true,
|
||||
"FullyIndirectEnum": true,
|
||||
"GroupNumericLiterals": true,
|
||||
"IdentifiersMustBeASCII": true,
|
||||
"NeverForceUnwrap": false,
|
||||
"NeverUseForceTry": false,
|
||||
"NeverUseImplicitlyUnwrappedOptionals": false,
|
||||
"NoAccessLevelOnExtensionDeclaration": false,
|
||||
"NoAssignmentInExpressions": true,
|
||||
"NoBlockComments": true,
|
||||
"NoCasesWithOnlyFallthrough": true,
|
||||
"NoEmptyTrailingClosureParentheses": true,
|
||||
"NoLabelsInCasePatterns": false,
|
||||
"NoLeadingUnderscores": false,
|
||||
"NoParensAroundConditions": true,
|
||||
"NoVoidReturnOnFunctionSignature": true,
|
||||
"OneCasePerLine": true,
|
||||
"OneVariableDeclarationPerLine": true,
|
||||
"OnlyOneTrailingClosureArgument": true,
|
||||
"OrderedImports": false,
|
||||
"ReturnVoidInsteadOfEmptyTuple": true,
|
||||
"UseEarlyExits": true,
|
||||
"UseLetInEveryBoundCaseVariable": false,
|
||||
"UseShorthandTypeNames": true,
|
||||
"UseSingleLinePropertyGetter": false,
|
||||
"UseSynthesizedInitializer": false,
|
||||
"UseTripleSlashForDocumentationComments": true,
|
||||
"UseWhereClausesInForLoops": false,
|
||||
"ValidateDocumentationComments": false
|
||||
},
|
||||
"spacesAroundRangeFormationOperators": false,
|
||||
"tabWidth": 8,
|
||||
"version": 1
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
# file options
|
||||
|
||||
--swiftversion 5.7
|
||||
--exclude .build
|
||||
|
||||
# format options
|
||||
|
||||
--self insert
|
||||
--patternlet inline
|
||||
--ranges nospace
|
||||
--stripunusedargs unnamed-only
|
||||
--ifdef no-indent
|
||||
--extensionacl on-declarations
|
||||
--disable typeSugar # https://github.com/nicklockwood/SwiftFormat/issues/636
|
||||
--disable andOperator
|
||||
--disable wrapMultilineStatementBraces
|
||||
--disable enumNamespaces
|
||||
--disable redundantExtensionACL
|
||||
--disable redundantReturn
|
||||
--disable preferKeyPath
|
||||
--disable sortedSwitchCases
|
||||
--disable numberFormatting
|
||||
|
||||
# rules
|
||||
@@ -15,8 +15,8 @@
|
||||
import Atomics
|
||||
import CoreMetrics
|
||||
|
||||
/// A counter is a cumulative metric that represents a single monotonically increasing counter whose value
|
||||
/// can only increase or be ``reset()`` to zero on restart.
|
||||
/// A counter is a cumulative metric that represents a single monotonically increasing
|
||||
/// counter whose value can only increase or be ``reset()`` to zero on restart.
|
||||
///
|
||||
/// For example, you can use a counter to represent the number of requests served, tasks completed, or errors.
|
||||
///
|
||||
@@ -68,7 +68,11 @@ public final class Counter: Sendable {
|
||||
while true {
|
||||
let bits = self.floatAtomic.load(ordering: .relaxed)
|
||||
let value = Double(bitPattern: bits) + amount
|
||||
let (exchanged, _) = self.floatAtomic.compareExchange(expected: bits, desired: value.bitPattern, ordering: .relaxed)
|
||||
let (exchanged, _) = self.floatAtomic.compareExchange(
|
||||
expected: bits,
|
||||
desired: value.bitPattern,
|
||||
ordering: .relaxed
|
||||
)
|
||||
if exchanged {
|
||||
break
|
||||
}
|
||||
|
||||
@@ -58,7 +58,11 @@ public final class Gauge: Sendable {
|
||||
while true {
|
||||
let bits = self.atomic.load(ordering: .relaxed)
|
||||
let value = Double(bitPattern: bits) + amount
|
||||
let (exchanged, _) = self.atomic.compareExchange(expected: bits, desired: value.bitPattern, ordering: .relaxed)
|
||||
let (exchanged, _) = self.atomic.compareExchange(
|
||||
expected: bits,
|
||||
desired: value.bitPattern,
|
||||
ordering: .relaxed
|
||||
)
|
||||
if exchanged {
|
||||
break
|
||||
}
|
||||
@@ -84,7 +88,7 @@ extension Gauge: CoreMetrics.MeterHandler {
|
||||
public func set(_ value: Double) {
|
||||
self.set(to: value)
|
||||
}
|
||||
|
||||
|
||||
public func set(_ value: Int64) {
|
||||
self.set(to: Double(value))
|
||||
}
|
||||
|
||||
@@ -47,16 +47,16 @@ typealias LockPrimitive = pthread_mutex_t
|
||||
#endif
|
||||
|
||||
@usableFromInline
|
||||
enum LockOperations { }
|
||||
enum LockOperations {}
|
||||
|
||||
extension LockOperations {
|
||||
@inlinable
|
||||
static func create(_ mutex: UnsafeMutablePointer<LockPrimitive>) {
|
||||
mutex.assertValidAlignment()
|
||||
|
||||
#if os(Windows)
|
||||
#if os(Windows)
|
||||
InitializeSRWLock(mutex)
|
||||
#else
|
||||
#else
|
||||
var attr = pthread_mutexattr_t()
|
||||
pthread_mutexattr_init(&attr)
|
||||
debugOnly {
|
||||
@@ -65,43 +65,43 @@ extension LockOperations {
|
||||
|
||||
let err = pthread_mutex_init(mutex, &attr)
|
||||
precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)")
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@inlinable
|
||||
static func destroy(_ mutex: UnsafeMutablePointer<LockPrimitive>) {
|
||||
mutex.assertValidAlignment()
|
||||
|
||||
#if os(Windows)
|
||||
#if os(Windows)
|
||||
// SRWLOCK does not need to be free'd
|
||||
#else
|
||||
#else
|
||||
let err = pthread_mutex_destroy(mutex)
|
||||
precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)")
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@inlinable
|
||||
static func lock(_ mutex: UnsafeMutablePointer<LockPrimitive>) {
|
||||
mutex.assertValidAlignment()
|
||||
|
||||
#if os(Windows)
|
||||
#if os(Windows)
|
||||
AcquireSRWLockExclusive(mutex)
|
||||
#else
|
||||
#else
|
||||
let err = pthread_mutex_lock(mutex)
|
||||
precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)")
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@inlinable
|
||||
static func unlock(_ mutex: UnsafeMutablePointer<LockPrimitive>) {
|
||||
mutex.assertValidAlignment()
|
||||
|
||||
#if os(Windows)
|
||||
#if os(Windows)
|
||||
ReleaseSRWLockExclusive(mutex)
|
||||
#else
|
||||
#else
|
||||
let err = pthread_mutex_unlock(mutex)
|
||||
precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)")
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ final class LockStorage<Value>: ManagedBuffer<Value, LockPrimitive> {
|
||||
}
|
||||
}
|
||||
|
||||
extension LockStorage: @unchecked Sendable { }
|
||||
extension LockStorage: @unchecked Sendable {}
|
||||
|
||||
/// A threading lock based on `libpthread` instead of `libdispatch`.
|
||||
///
|
||||
@@ -251,7 +251,7 @@ extension NIOLock {
|
||||
}
|
||||
|
||||
@inlinable
|
||||
func withLockVoid(_ body: () throws -> Void) rethrows -> Void {
|
||||
func withLockVoid(_ body: () throws -> Void) rethrows {
|
||||
try self.withLock(body)
|
||||
}
|
||||
}
|
||||
@@ -272,6 +272,10 @@ extension UnsafeMutablePointer {
|
||||
/// https://forums.swift.org/t/support-debug-only-code/11037 for a discussion.
|
||||
@inlinable
|
||||
internal func debugOnly(_ body: () -> Void) {
|
||||
assert({ body(); return true }())
|
||||
assert(
|
||||
{
|
||||
body()
|
||||
return true
|
||||
}()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -74,21 +74,21 @@ public final class PrometheusCollectorRegistry: Sendable {
|
||||
/// - Returns: A ``Counter`` that is registered with this ``PrometheusCollectorRegistry``
|
||||
public func makeCounter(name: String) -> Counter {
|
||||
self.box.withLockedValue { store -> Counter in
|
||||
if let value = store[name] {
|
||||
guard case .counter(let counter) = value else {
|
||||
fatalError("""
|
||||
Could not make Counter with name: \(name), since another metric type
|
||||
already exists for the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
return counter
|
||||
} else {
|
||||
guard let value = store[name] else {
|
||||
let counter = Counter(name: name, labels: [])
|
||||
store[name] = .counter(counter)
|
||||
return counter
|
||||
}
|
||||
guard case .counter(let counter) = value else {
|
||||
fatalError(
|
||||
"""
|
||||
Could not make Counter with name: \(name), since another metric type
|
||||
already exists for the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
return counter
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,41 +107,42 @@ public final class PrometheusCollectorRegistry: Sendable {
|
||||
}
|
||||
|
||||
return self.box.withLockedValue { store -> Counter in
|
||||
if let value = store[name] {
|
||||
guard case .counterWithLabels(let labelNames, var dimensionLookup) = value else {
|
||||
fatalError("""
|
||||
Could not make Counter with name: \(name) and labels: \(labels), since another
|
||||
metric type already exists for the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
let key = LabelsKey(labels)
|
||||
if let counter = dimensionLookup[key] {
|
||||
return counter
|
||||
}
|
||||
|
||||
// check if all labels match the already existing ones.
|
||||
if labelNames != labels.allLabelNames {
|
||||
fatalError("""
|
||||
Could not make Counter with name: \(name) and labels: \(labels), since the
|
||||
label names don't match the label names of previously registered Counters with
|
||||
the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
let counter = Counter(name: name, labels: labels)
|
||||
dimensionLookup[key] = counter
|
||||
store[name] = .counterWithLabels(labelNames, dimensionLookup)
|
||||
return counter
|
||||
} else {
|
||||
guard let value = store[name] else {
|
||||
let labelNames = labels.allLabelNames
|
||||
let counter = Counter(name: name, labels: labels)
|
||||
|
||||
store[name] = .counterWithLabels(labelNames, [LabelsKey(labels): counter])
|
||||
return counter
|
||||
}
|
||||
guard case .counterWithLabels(let labelNames, var dimensionLookup) = value else {
|
||||
fatalError(
|
||||
"""
|
||||
Could not make Counter with name: \(name) and labels: \(labels), since another
|
||||
metric type already exists for the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
let key = LabelsKey(labels)
|
||||
if let counter = dimensionLookup[key] {
|
||||
return counter
|
||||
}
|
||||
|
||||
// check if all labels match the already existing ones.
|
||||
if labelNames != labels.allLabelNames {
|
||||
fatalError(
|
||||
"""
|
||||
Could not make Counter with name: \(name) and labels: \(labels), since the
|
||||
label names don't match the label names of previously registered Counters with
|
||||
the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
let counter = Counter(name: name, labels: labels)
|
||||
dimensionLookup[key] = counter
|
||||
store[name] = .counterWithLabels(labelNames, dimensionLookup)
|
||||
return counter
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,21 +155,21 @@ public final class PrometheusCollectorRegistry: Sendable {
|
||||
/// - Returns: A ``Gauge`` that is registered with this ``PrometheusCollectorRegistry``
|
||||
public func makeGauge(name: String) -> Gauge {
|
||||
self.box.withLockedValue { store -> Gauge in
|
||||
if let value = store[name] {
|
||||
guard case .gauge(let gauge) = value else {
|
||||
fatalError("""
|
||||
Could not make Gauge with name: \(name), since another metric type already
|
||||
exists for the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
return gauge
|
||||
} else {
|
||||
guard let value = store[name] else {
|
||||
let gauge = Gauge(name: name, labels: [])
|
||||
store[name] = .gauge(gauge)
|
||||
return gauge
|
||||
}
|
||||
guard case .gauge(let gauge) = value else {
|
||||
fatalError(
|
||||
"""
|
||||
Could not make Gauge with name: \(name), since another metric type already
|
||||
exists for the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
return gauge
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,41 +188,42 @@ public final class PrometheusCollectorRegistry: Sendable {
|
||||
}
|
||||
|
||||
return self.box.withLockedValue { store -> Gauge in
|
||||
if let value = store[name] {
|
||||
guard case .gaugeWithLabels(let labelNames, var dimensionLookup) = value else {
|
||||
fatalError("""
|
||||
Could not make Gauge with name: \(name) and labels: \(labels), since another
|
||||
metric type already exists for the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
let key = LabelsKey(labels)
|
||||
if let gauge = dimensionLookup[key] {
|
||||
return gauge
|
||||
}
|
||||
|
||||
// check if all labels match the already existing ones.
|
||||
if labelNames != labels.allLabelNames {
|
||||
fatalError("""
|
||||
Could not make Gauge with name: \(name) and labels: \(labels), since the
|
||||
label names don't match the label names of previously registered Gauges with
|
||||
the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
let gauge = Gauge(name: name, labels: labels)
|
||||
dimensionLookup[key] = gauge
|
||||
store[name] = .gaugeWithLabels(labelNames, dimensionLookup)
|
||||
return gauge
|
||||
} else {
|
||||
guard let value = store[name] else {
|
||||
let labelNames = labels.allLabelNames
|
||||
let gauge = Gauge(name: name, labels: labels)
|
||||
|
||||
store[name] = .gaugeWithLabels(labelNames, [LabelsKey(labels): gauge])
|
||||
return gauge
|
||||
}
|
||||
guard case .gaugeWithLabels(let labelNames, var dimensionLookup) = value else {
|
||||
fatalError(
|
||||
"""
|
||||
Could not make Gauge with name: \(name) and labels: \(labels), since another
|
||||
metric type already exists for the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
let key = LabelsKey(labels)
|
||||
if let gauge = dimensionLookup[key] {
|
||||
return gauge
|
||||
}
|
||||
|
||||
// check if all labels match the already existing ones.
|
||||
if labelNames != labels.allLabelNames {
|
||||
fatalError(
|
||||
"""
|
||||
Could not make Gauge with name: \(name) and labels: \(labels), since the
|
||||
label names don't match the label names of previously registered Gauges with
|
||||
the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
let gauge = Gauge(name: name, labels: labels)
|
||||
dimensionLookup[key] = gauge
|
||||
store[name] = .gaugeWithLabels(labelNames, dimensionLookup)
|
||||
return gauge
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,21 +237,21 @@ public final class PrometheusCollectorRegistry: Sendable {
|
||||
/// - Returns: A ``DurationHistogram`` that is registered with this ``PrometheusCollectorRegistry``
|
||||
public func makeDurationHistogram(name: String, buckets: [Duration]) -> DurationHistogram {
|
||||
self.box.withLockedValue { store -> DurationHistogram in
|
||||
if let value = store[name] {
|
||||
guard case .durationHistogram(let histogram) = value else {
|
||||
fatalError("""
|
||||
Could not make DurationHistogram with name: \(name), since another
|
||||
metric type already exists for the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
return histogram
|
||||
} else {
|
||||
guard let value = store[name] else {
|
||||
let gauge = DurationHistogram(name: name, labels: [], buckets: buckets)
|
||||
store[name] = .durationHistogram(gauge)
|
||||
return gauge
|
||||
}
|
||||
guard case .durationHistogram(let histogram) = value else {
|
||||
fatalError(
|
||||
"""
|
||||
Could not make DurationHistogram with name: \(name), since another
|
||||
metric type already exists for the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
return histogram
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,57 +265,64 @@ public final class PrometheusCollectorRegistry: Sendable {
|
||||
/// what’s actually being measured in a Prometheus metric.
|
||||
/// - Parameter buckets: Define the buckets that shall be used within the ``DurationHistogram``
|
||||
/// - Returns: A ``DurationHistogram`` that is registered with this ``PrometheusCollectorRegistry``
|
||||
public func makeDurationHistogram(name: String, labels: [(String, String)], buckets: [Duration]) -> DurationHistogram {
|
||||
public func makeDurationHistogram(
|
||||
name: String,
|
||||
labels: [(String, String)],
|
||||
buckets: [Duration]
|
||||
) -> DurationHistogram {
|
||||
guard !labels.isEmpty else {
|
||||
return self.makeDurationHistogram(name: name, buckets: buckets)
|
||||
}
|
||||
|
||||
return self.box.withLockedValue { store -> DurationHistogram in
|
||||
if let value = store[name] {
|
||||
guard case .durationHistogramWithLabels(let labelNames, var dimensionLookup, let storedBuckets) = value else {
|
||||
fatalError("""
|
||||
Could not make DurationHistogram with name: \(name) and labels: \(labels), since another
|
||||
metric type already exists for the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
let key = LabelsKey(labels)
|
||||
if let histogram = dimensionLookup[key] {
|
||||
return histogram
|
||||
}
|
||||
|
||||
// check if all labels match the already existing ones.
|
||||
if labelNames != labels.allLabelNames {
|
||||
fatalError("""
|
||||
Could not make DurationHistogram with name: \(name) and labels: \(labels), since the
|
||||
label names don't match the label names of previously registered Gauges with
|
||||
the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
if storedBuckets != buckets {
|
||||
fatalError("""
|
||||
Could not make DurationHistogram with name: \(name) and labels: \(labels), since the
|
||||
buckets don't match the buckets of previously registered TimeHistograms with
|
||||
the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
precondition(storedBuckets == buckets)
|
||||
|
||||
let histogram = DurationHistogram(name: name, labels: labels, buckets: storedBuckets)
|
||||
dimensionLookup[key] = histogram
|
||||
store[name] = .durationHistogramWithLabels(labelNames, dimensionLookup, storedBuckets)
|
||||
return histogram
|
||||
} else {
|
||||
guard let value = store[name] else {
|
||||
let labelNames = labels.allLabelNames
|
||||
let histogram = DurationHistogram(name: name, labels: labels, buckets: buckets)
|
||||
|
||||
store[name] = .durationHistogramWithLabels(labelNames, [LabelsKey(labels): histogram], buckets)
|
||||
return histogram
|
||||
}
|
||||
guard case .durationHistogramWithLabels(let labelNames, var dimensionLookup, let storedBuckets) = value
|
||||
else {
|
||||
fatalError(
|
||||
"""
|
||||
Could not make DurationHistogram with name: \(name) and labels: \(labels), since another
|
||||
metric type already exists for the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
let key = LabelsKey(labels)
|
||||
if let histogram = dimensionLookup[key] {
|
||||
return histogram
|
||||
}
|
||||
|
||||
// check if all labels match the already existing ones.
|
||||
if labelNames != labels.allLabelNames {
|
||||
fatalError(
|
||||
"""
|
||||
Could not make DurationHistogram with name: \(name) and labels: \(labels), since the
|
||||
label names don't match the label names of previously registered Gauges with
|
||||
the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
if storedBuckets != buckets {
|
||||
fatalError(
|
||||
"""
|
||||
Could not make DurationHistogram with name: \(name) and labels: \(labels), since the
|
||||
buckets don't match the buckets of previously registered TimeHistograms with
|
||||
the same name.
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
precondition(storedBuckets == buckets)
|
||||
|
||||
let histogram = DurationHistogram(name: name, labels: labels, buckets: storedBuckets)
|
||||
dimensionLookup[key] = histogram
|
||||
store[name] = .durationHistogramWithLabels(labelNames, dimensionLookup, storedBuckets)
|
||||
return histogram
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,17 +336,16 @@ public final class PrometheusCollectorRegistry: Sendable {
|
||||
/// - Returns: A ``ValueHistogram`` that is registered with this ``PrometheusCollectorRegistry``
|
||||
public func makeValueHistogram(name: String, buckets: [Double]) -> ValueHistogram {
|
||||
self.box.withLockedValue { store -> ValueHistogram in
|
||||
if let value = store[name] {
|
||||
guard case .valueHistogram(let histogram) = value else {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
return histogram
|
||||
} else {
|
||||
guard let value = store[name] else {
|
||||
let gauge = ValueHistogram(name: name, labels: [], buckets: buckets)
|
||||
store[name] = .valueHistogram(gauge)
|
||||
return gauge
|
||||
}
|
||||
guard case .valueHistogram(let histogram) = value else {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
return histogram
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,36 +365,35 @@ public final class PrometheusCollectorRegistry: Sendable {
|
||||
}
|
||||
|
||||
return self.box.withLockedValue { store -> ValueHistogram in
|
||||
if let value = store[name] {
|
||||
guard case .valueHistogramWithLabels(let labelNames, var dimensionLookup, let storedBuckets) = value else {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
let key = LabelsKey(labels)
|
||||
if let histogram = dimensionLookup[key] {
|
||||
return histogram
|
||||
}
|
||||
|
||||
// check if all labels match the already existing ones.
|
||||
precondition(labelNames == labels.allLabelNames)
|
||||
precondition(storedBuckets == buckets)
|
||||
|
||||
let histogram = ValueHistogram(name: name, labels: labels, buckets: storedBuckets)
|
||||
dimensionLookup[key] = histogram
|
||||
store[name] = .valueHistogramWithLabels(labelNames, dimensionLookup, storedBuckets)
|
||||
return histogram
|
||||
} else {
|
||||
guard let value = store[name] else {
|
||||
let labelNames = labels.allLabelNames
|
||||
let histogram = ValueHistogram(name: name, labels: labels, buckets: buckets)
|
||||
|
||||
store[name] = .valueHistogramWithLabels(labelNames, [LabelsKey(labels): histogram], buckets)
|
||||
return histogram
|
||||
}
|
||||
guard case .valueHistogramWithLabels(let labelNames, var dimensionLookup, let storedBuckets) = value else {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
let key = LabelsKey(labels)
|
||||
if let histogram = dimensionLookup[key] {
|
||||
return histogram
|
||||
}
|
||||
|
||||
// check if all labels match the already existing ones.
|
||||
precondition(labelNames == labels.allLabelNames)
|
||||
precondition(storedBuckets == buckets)
|
||||
|
||||
let histogram = ValueHistogram(name: name, labels: labels, buckets: storedBuckets)
|
||||
dimensionLookup[key] = histogram
|
||||
store[name] = .valueHistogramWithLabels(labelNames, dimensionLookup, storedBuckets)
|
||||
return histogram
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Destroying Metrics
|
||||
|
||||
|
||||
/// Unregisters a ``Counter`` from the ``PrometheusCollectorRegistry``. This means that the provided ``Counter``
|
||||
/// will not be included in future ``emit(into:)`` calls.
|
||||
///
|
||||
@@ -526,7 +533,7 @@ public final class PrometheusCollectorRegistry: Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
extension Array<(String, String)> {
|
||||
extension [(String, String)] {
|
||||
fileprivate var allLabelNames: [String] {
|
||||
var result = [String]()
|
||||
result.reserveCapacity(self.count)
|
||||
@@ -539,7 +546,7 @@ extension Array<(String, String)> {
|
||||
}
|
||||
}
|
||||
|
||||
extension Array<UInt8> {
|
||||
extension [UInt8] {
|
||||
fileprivate mutating func addTypeLine(label: String, type: String) {
|
||||
self.append(contentsOf: #"# TYPE "#.utf8)
|
||||
self.append(contentsOf: label.utf8)
|
||||
|
||||
@@ -45,7 +45,8 @@ public struct PrometheusMetricsFactory: Sendable {
|
||||
|
||||
/// A closure to modify the name and labels used in the Swift Metrics API. This allows users
|
||||
/// to overwrite the Metric names in third party packages.
|
||||
public var nameAndLabelSanitizer: @Sendable (_ name: String, _ labels: [(String, String)]) -> (String, [(String, String)])
|
||||
public var nameAndLabelSanitizer:
|
||||
@Sendable (_ name: String, _ labels: [(String, String)]) -> (String, [(String, String)])
|
||||
|
||||
public init(registry: PrometheusCollectorRegistry = Self.defaultRegistry) {
|
||||
self.registry = registry
|
||||
@@ -95,14 +96,17 @@ extension PrometheusMetricsFactory: CoreMetrics.MetricsFactory {
|
||||
return self.registry.makeCounter(name: label, labels: dimensions)
|
||||
}
|
||||
|
||||
public func makeRecorder(label: String, dimensions: [(String, String)], aggregate: Bool) -> CoreMetrics.RecorderHandler {
|
||||
public func makeRecorder(
|
||||
label: String,
|
||||
dimensions: [(String, String)],
|
||||
aggregate: Bool
|
||||
) -> CoreMetrics.RecorderHandler {
|
||||
let (label, dimensions) = self.nameAndLabelSanitizer(label, dimensions)
|
||||
if aggregate {
|
||||
let buckets = self.valueHistogramBuckets[label] ?? self.defaultValueHistogramBuckets
|
||||
return self.registry.makeValueHistogram(name: label, labels: dimensions, buckets: buckets)
|
||||
} else {
|
||||
guard aggregate else {
|
||||
return self.registry.makeGauge(name: label, labels: dimensions)
|
||||
}
|
||||
let buckets = self.valueHistogramBuckets[label] ?? self.defaultValueHistogramBuckets
|
||||
return self.registry.makeValueHistogram(name: label, labels: dimensions, buckets: buckets)
|
||||
}
|
||||
|
||||
public func makeMeter(label: String, dimensions: [(String, String)]) -> CoreMetrics.MeterHandler {
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import XCTest
|
||||
import Prometheus
|
||||
import XCTest
|
||||
|
||||
final class CounterTests: XCTestCase {
|
||||
func testCounterWithoutLabels() {
|
||||
@@ -22,17 +22,22 @@ final class CounterTests: XCTestCase {
|
||||
|
||||
var buffer = [UInt8]()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo counter
|
||||
foo 0
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo counter
|
||||
foo 0
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
// Increment by 1
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
counter.increment()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo counter
|
||||
foo 1
|
||||
|
||||
@@ -43,41 +48,53 @@ final class CounterTests: XCTestCase {
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
counter.increment()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo counter
|
||||
foo 2
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo counter
|
||||
foo 2
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
// Increment by 2
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
counter.increment(by: Int64(2))
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo counter
|
||||
foo 4
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo counter
|
||||
foo 4
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
// Increment by 2.5
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
counter.increment(by: 2.5)
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo counter
|
||||
foo 6.5
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo counter
|
||||
foo 6.5
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
// Reset
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
counter.reset()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo counter
|
||||
foo 0
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo counter
|
||||
foo 0
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testCounterWithLabels() {
|
||||
@@ -86,51 +103,65 @@ final class CounterTests: XCTestCase {
|
||||
|
||||
var buffer = [UInt8]()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo counter
|
||||
foo{bar="baz"} 0
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo counter
|
||||
foo{bar="baz"} 0
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
// Increment by 1
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
counter.increment()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo counter
|
||||
foo{bar="baz"} 1
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo counter
|
||||
foo{bar="baz"} 1
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
// Increment by 1
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
counter.increment()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo counter
|
||||
foo{bar="baz"} 2
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo counter
|
||||
foo{bar="baz"} 2
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
// Increment by 2
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
counter.increment(by: Int64(2))
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo counter
|
||||
foo{bar="baz"} 4
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo counter
|
||||
foo{bar="baz"} 4
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
// Reset
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
counter.reset()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo counter
|
||||
foo{bar="baz"} 0
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo counter
|
||||
foo{bar="baz"} 0
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import XCTest
|
||||
import Prometheus
|
||||
import XCTest
|
||||
|
||||
final class GaugeTests: XCTestCase {
|
||||
func testGaugeWithoutLabels() {
|
||||
@@ -22,51 +22,66 @@ final class GaugeTests: XCTestCase {
|
||||
|
||||
var buffer = [UInt8]()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo gauge
|
||||
foo 0.0
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo gauge
|
||||
foo 0.0
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
// Set to 1
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
gauge.record(Int64(1))
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo gauge
|
||||
foo 1.0
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo gauge
|
||||
foo 1.0
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
// Set to 2
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
gauge.record(Int64(2))
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo gauge
|
||||
foo 2.0
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo gauge
|
||||
foo 2.0
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
// Set to 4
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
gauge.record(Int64(4))
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo gauge
|
||||
foo 4.0
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo gauge
|
||||
foo 4.0
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
// Reset
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
gauge.record(Int64(0))
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo gauge
|
||||
foo 0.0
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo gauge
|
||||
foo 0.0
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testGaugeWithLabels() {
|
||||
@@ -75,57 +90,72 @@ final class GaugeTests: XCTestCase {
|
||||
|
||||
var buffer = [UInt8]()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo gauge
|
||||
foo{bar="baz"} 0.0
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo gauge
|
||||
foo{bar="baz"} 0.0
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
// Set to 1
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
gauge.record(Int64(1))
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo gauge
|
||||
foo{bar="baz"} 1.0
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo gauge
|
||||
foo{bar="baz"} 1.0
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
// Set to 2
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
gauge.record(Int64(2))
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo gauge
|
||||
foo{bar="baz"} 2.0
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo gauge
|
||||
foo{bar="baz"} 2.0
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
// Set to 4
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
gauge.record(Int64(4))
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo gauge
|
||||
foo{bar="baz"} 4.0
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo gauge
|
||||
foo{bar="baz"} 4.0
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
// Reset
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
gauge.record(Int64(0))
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
# TYPE foo gauge
|
||||
foo{bar="baz"} 0.0
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo gauge
|
||||
foo{bar="baz"} 0.0
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testGaugeSetToFromMultipleTasks() async {
|
||||
let client = PrometheusCollectorRegistry()
|
||||
let gauge = client.makeGauge(name: "foo", labels: [("bar", "baz")])
|
||||
await withTaskGroup(of: Void.self){ group in
|
||||
await withTaskGroup(of: Void.self) { group in
|
||||
for _ in 0..<100_000 {
|
||||
group.addTask {
|
||||
gauge.set(to: Double.random(in: 0..<20))
|
||||
@@ -137,7 +167,7 @@ final class GaugeTests: XCTestCase {
|
||||
func testIncByFromMultipleTasks() async {
|
||||
let client = PrometheusCollectorRegistry()
|
||||
let gauge = client.makeGauge(name: "foo", labels: [("bar", "baz")])
|
||||
await withTaskGroup(of: Void.self){ group in
|
||||
await withTaskGroup(of: Void.self) { group in
|
||||
for _ in 0..<100_000 {
|
||||
group.addTask {
|
||||
gauge.increment(by: Double.random(in: 0..<1))
|
||||
@@ -146,4 +176,3 @@ final class GaugeTests: XCTestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,23 +12,29 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import XCTest
|
||||
import Prometheus
|
||||
import XCTest
|
||||
|
||||
final class HistogramTests: XCTestCase {
|
||||
func testHistogramWithoutDimensions() {
|
||||
let client = PrometheusCollectorRegistry()
|
||||
let histogram = client.makeDurationHistogram(name: "foo", labels: [], buckets: [
|
||||
.milliseconds(100),
|
||||
.milliseconds(250),
|
||||
.milliseconds(500),
|
||||
.seconds(1),
|
||||
])
|
||||
let histogram = client.makeDurationHistogram(
|
||||
name: "foo",
|
||||
labels: [],
|
||||
buckets: [
|
||||
.milliseconds(100),
|
||||
.milliseconds(250),
|
||||
.milliseconds(500),
|
||||
.seconds(1),
|
||||
]
|
||||
)
|
||||
|
||||
var buffer = [UInt8]()
|
||||
client.emit(into: &buffer)
|
||||
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{le="0.1"} 0
|
||||
foo_bucket{le="0.25"} 0
|
||||
@@ -43,9 +49,14 @@ final class HistogramTests: XCTestCase {
|
||||
|
||||
// Record 400ms
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
histogram.recordNanoseconds(400_000_000) // 400ms
|
||||
histogram.recordNanoseconds(400_000_000) // 400ms
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(
|
||||
decoding: buffer,
|
||||
as: Unicode.UTF8.self
|
||||
),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{le="0.1"} 0
|
||||
foo_bucket{le="0.25"} 0
|
||||
@@ -60,9 +71,11 @@ final class HistogramTests: XCTestCase {
|
||||
|
||||
// Record 600ms
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
histogram.recordNanoseconds(600_000_000) // 600ms
|
||||
histogram.recordNanoseconds(600_000_000) // 600ms
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{le="0.1"} 0
|
||||
foo_bucket{le="0.25"} 0
|
||||
@@ -77,9 +90,11 @@ final class HistogramTests: XCTestCase {
|
||||
|
||||
// Record 1200ms
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
histogram.recordNanoseconds(1_200_000_000) // 1200ms
|
||||
histogram.recordNanoseconds(1_200_000_000) // 1200ms
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{le="0.1"} 0
|
||||
foo_bucket{le="0.25"} 0
|
||||
@@ -94,9 +109,11 @@ final class HistogramTests: XCTestCase {
|
||||
|
||||
// Record 80ms
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
histogram.recordNanoseconds(80_000_000) // 80ms
|
||||
histogram.recordNanoseconds(80_000_000) // 80ms
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{le="0.1"} 1
|
||||
foo_bucket{le="0.25"} 1
|
||||
@@ -112,16 +129,22 @@ final class HistogramTests: XCTestCase {
|
||||
|
||||
func testHistogramWithOneDimension() {
|
||||
let client = PrometheusCollectorRegistry()
|
||||
let histogram = client.makeDurationHistogram(name: "foo", labels: [("bar", "baz")], buckets: [
|
||||
.milliseconds(100),
|
||||
.milliseconds(250),
|
||||
.milliseconds(500),
|
||||
.seconds(1),
|
||||
])
|
||||
let histogram = client.makeDurationHistogram(
|
||||
name: "foo",
|
||||
labels: [("bar", "baz")],
|
||||
buckets: [
|
||||
.milliseconds(100),
|
||||
.milliseconds(250),
|
||||
.milliseconds(500),
|
||||
.seconds(1),
|
||||
]
|
||||
)
|
||||
|
||||
var buffer = [UInt8]()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{bar="baz",le="0.1"} 0
|
||||
foo_bucket{bar="baz",le="0.25"} 0
|
||||
@@ -136,9 +159,11 @@ final class HistogramTests: XCTestCase {
|
||||
|
||||
// Record 400ms
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
histogram.recordNanoseconds(400_000_000) // 400ms
|
||||
histogram.recordNanoseconds(400_000_000) // 400ms
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{bar="baz",le="0.1"} 0
|
||||
foo_bucket{bar="baz",le="0.25"} 0
|
||||
@@ -153,9 +178,11 @@ final class HistogramTests: XCTestCase {
|
||||
|
||||
// Record 600ms
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
histogram.recordNanoseconds(600_000_000) // 600ms
|
||||
histogram.recordNanoseconds(600_000_000) // 600ms
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{bar="baz",le="0.1"} 0
|
||||
foo_bucket{bar="baz",le="0.25"} 0
|
||||
@@ -170,9 +197,11 @@ final class HistogramTests: XCTestCase {
|
||||
|
||||
// Record 1200ms
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
histogram.recordNanoseconds(1_200_000_000) // 1200ms
|
||||
histogram.recordNanoseconds(1_200_000_000) // 1200ms
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{bar="baz",le="0.1"} 0
|
||||
foo_bucket{bar="baz",le="0.25"} 0
|
||||
@@ -187,9 +216,11 @@ final class HistogramTests: XCTestCase {
|
||||
|
||||
// Record 80ms
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
histogram.recordNanoseconds(80_000_000) // 80ms
|
||||
histogram.recordNanoseconds(80_000_000) // 80ms
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{bar="baz",le="0.1"} 1
|
||||
foo_bucket{bar="baz",le="0.25"} 1
|
||||
@@ -205,16 +236,22 @@ final class HistogramTests: XCTestCase {
|
||||
|
||||
func testHistogramWithTwoDimension() {
|
||||
let client = PrometheusCollectorRegistry()
|
||||
let histogram = client.makeDurationHistogram(name: "foo", labels: [("bar", "baz"), ("abc", "xyz")], buckets: [
|
||||
.milliseconds(100),
|
||||
.milliseconds(250),
|
||||
.milliseconds(500),
|
||||
.seconds(1),
|
||||
])
|
||||
let histogram = client.makeDurationHistogram(
|
||||
name: "foo",
|
||||
labels: [("bar", "baz"), ("abc", "xyz")],
|
||||
buckets: [
|
||||
.milliseconds(100),
|
||||
.milliseconds(250),
|
||||
.milliseconds(500),
|
||||
.seconds(1),
|
||||
]
|
||||
)
|
||||
|
||||
var buffer = [UInt8]()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{bar="baz",abc="xyz",le="0.1"} 0
|
||||
foo_bucket{bar="baz",abc="xyz",le="0.25"} 0
|
||||
@@ -229,9 +266,11 @@ final class HistogramTests: XCTestCase {
|
||||
|
||||
// Record 400ms
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
histogram.recordNanoseconds(400_000_000) // 400ms
|
||||
histogram.recordNanoseconds(400_000_000) // 400ms
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{bar="baz",abc="xyz",le="0.1"} 0
|
||||
foo_bucket{bar="baz",abc="xyz",le="0.25"} 0
|
||||
@@ -246,9 +285,11 @@ final class HistogramTests: XCTestCase {
|
||||
|
||||
// Record 600ms
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
histogram.recordNanoseconds(600_000_000) // 600ms
|
||||
histogram.recordNanoseconds(600_000_000) // 600ms
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{bar="baz",abc="xyz",le="0.1"} 0
|
||||
foo_bucket{bar="baz",abc="xyz",le="0.25"} 0
|
||||
@@ -263,9 +304,11 @@ final class HistogramTests: XCTestCase {
|
||||
|
||||
// Record 1200ms
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
histogram.recordNanoseconds(1_200_000_000) // 1200ms
|
||||
histogram.recordNanoseconds(1_200_000_000) // 1200ms
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{bar="baz",abc="xyz",le="0.1"} 0
|
||||
foo_bucket{bar="baz",abc="xyz",le="0.25"} 0
|
||||
@@ -280,9 +323,11 @@ final class HistogramTests: XCTestCase {
|
||||
|
||||
// Record 80ms
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
histogram.recordNanoseconds(80_000_000) // 80ms
|
||||
histogram.recordNanoseconds(80_000_000) // 80ms
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{bar="baz",abc="xyz",le="0.1"} 1
|
||||
foo_bucket{bar="baz",abc="xyz",le="0.25"} 1
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import XCTest
|
||||
import Prometheus
|
||||
import XCTest
|
||||
|
||||
final class PrometheusCollectorRegistryTests: XCTestCase {
|
||||
func testAskingForTheSameCounterReturnsTheSameCounter() {
|
||||
@@ -27,7 +27,9 @@ final class PrometheusCollectorRegistryTests: XCTestCase {
|
||||
|
||||
var buffer = [UInt8]()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo counter
|
||||
foo 3
|
||||
|
||||
@@ -46,7 +48,9 @@ final class PrometheusCollectorRegistryTests: XCTestCase {
|
||||
|
||||
var buffer = [UInt8]()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo counter
|
||||
foo{bar="baz"} 3
|
||||
|
||||
@@ -71,7 +75,6 @@ final class PrometheusCollectorRegistryTests: XCTestCase {
|
||||
XCTAssert(output.contains(#"foo{bar="xyz"} 2\#n"#))
|
||||
}
|
||||
|
||||
|
||||
func testAskingForTheSameGaugeReturnsTheSameGauge() {
|
||||
let client = PrometheusCollectorRegistry()
|
||||
let gauge1 = client.makeGauge(name: "foo")
|
||||
@@ -84,7 +87,9 @@ final class PrometheusCollectorRegistryTests: XCTestCase {
|
||||
|
||||
var buffer = [UInt8]()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo gauge
|
||||
foo 3.0
|
||||
|
||||
@@ -104,7 +109,9 @@ final class PrometheusCollectorRegistryTests: XCTestCase {
|
||||
|
||||
var buffer = [UInt8]()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo gauge
|
||||
foo{bar="baz"} 3.0
|
||||
|
||||
@@ -112,7 +119,6 @@ final class PrometheusCollectorRegistryTests: XCTestCase {
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
func testAskingForTheSameTimeHistogramReturnsTheSameTimeHistogram() {
|
||||
let client = PrometheusCollectorRegistry()
|
||||
let histogram1 = client.makeDurationHistogram(name: "foo", buckets: [.seconds(1), .seconds(2), .seconds(3)])
|
||||
@@ -124,7 +130,9 @@ final class PrometheusCollectorRegistryTests: XCTestCase {
|
||||
|
||||
var buffer = [UInt8]()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{le="1.0"} 0
|
||||
foo_bucket{le="2.0"} 1
|
||||
@@ -139,8 +147,16 @@ final class PrometheusCollectorRegistryTests: XCTestCase {
|
||||
|
||||
func testAskingForTheSameTimeHistogramWithLabelsReturnsTheSameTimeHistogram() {
|
||||
let client = PrometheusCollectorRegistry()
|
||||
let histogram1 = client.makeDurationHistogram(name: "foo", labels: [("bar", "baz")], buckets: [.seconds(1), .seconds(2), .seconds(3)])
|
||||
let histogram2 = client.makeDurationHistogram(name: "foo", labels: [("bar", "baz")], buckets: [.seconds(1), .seconds(2), .seconds(3)])
|
||||
let histogram1 = client.makeDurationHistogram(
|
||||
name: "foo",
|
||||
labels: [("bar", "baz")],
|
||||
buckets: [.seconds(1), .seconds(2), .seconds(3)]
|
||||
)
|
||||
let histogram2 = client.makeDurationHistogram(
|
||||
name: "foo",
|
||||
labels: [("bar", "baz")],
|
||||
buckets: [.seconds(1), .seconds(2), .seconds(3)]
|
||||
)
|
||||
|
||||
XCTAssert(histogram1 === histogram2)
|
||||
histogram1.record(.milliseconds(2500))
|
||||
@@ -148,7 +164,9 @@ final class PrometheusCollectorRegistryTests: XCTestCase {
|
||||
|
||||
var buffer = [UInt8]()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{bar="baz",le="1.0"} 0
|
||||
foo_bucket{bar="baz",le="2.0"} 1
|
||||
@@ -161,7 +179,6 @@ final class PrometheusCollectorRegistryTests: XCTestCase {
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
func testAskingForTheSameValueHistogramReturnsTheSameTimeHistogram() {
|
||||
let client = PrometheusCollectorRegistry()
|
||||
let histogram1 = client.makeValueHistogram(name: "foo", buckets: [1, 2, 3])
|
||||
@@ -173,7 +190,9 @@ final class PrometheusCollectorRegistryTests: XCTestCase {
|
||||
|
||||
var buffer = [UInt8]()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{le="1.0"} 0
|
||||
foo_bucket{le="2.0"} 1
|
||||
@@ -197,7 +216,9 @@ final class PrometheusCollectorRegistryTests: XCTestCase {
|
||||
|
||||
var buffer = [UInt8]()
|
||||
client.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo histogram
|
||||
foo_bucket{bar="baz",le="1.0"} 0
|
||||
foo_bucket{bar="baz",le="2.0"} 1
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import XCTest
|
||||
import Prometheus
|
||||
import XCTest
|
||||
|
||||
final class PrometheusMetricsFactoryTests: XCTestCase {
|
||||
func testMakeTimers() {
|
||||
@@ -52,7 +52,9 @@ final class PrometheusMetricsFactoryTests: XCTestCase {
|
||||
|
||||
var buffer = [UInt8]()
|
||||
registry.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo counter
|
||||
foo{bar="baz"} 3.5
|
||||
|
||||
@@ -62,7 +64,9 @@ final class PrometheusMetricsFactoryTests: XCTestCase {
|
||||
factory.destroyCounter(maybeCounter)
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
registry.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo counter
|
||||
|
||||
"""
|
||||
@@ -81,7 +85,9 @@ final class PrometheusMetricsFactoryTests: XCTestCase {
|
||||
|
||||
var buffer = [UInt8]()
|
||||
registry.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo gauge
|
||||
foo{bar="baz"} -6.0
|
||||
|
||||
@@ -92,7 +98,9 @@ final class PrometheusMetricsFactoryTests: XCTestCase {
|
||||
maybeGauge.set(12.45)
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
registry.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo gauge
|
||||
foo{bar="baz"} 12.45
|
||||
|
||||
@@ -100,10 +108,12 @@ final class PrometheusMetricsFactoryTests: XCTestCase {
|
||||
)
|
||||
|
||||
// set to int value
|
||||
maybeGauge.set(Int64(42)) // needs explicit cast... otherwise ambigious
|
||||
maybeGauge.set(Int64(42)) // needs explicit cast... otherwise ambigious
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
registry.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo gauge
|
||||
foo{bar="baz"} 42.0
|
||||
|
||||
@@ -113,7 +123,9 @@ final class PrometheusMetricsFactoryTests: XCTestCase {
|
||||
factory.destroyMeter(maybeGauge)
|
||||
buffer.removeAll(keepingCapacity: true)
|
||||
registry.emit(into: &buffer)
|
||||
XCTAssertEqual(String(decoding: buffer, as: Unicode.UTF8.self), """
|
||||
XCTAssertEqual(
|
||||
String(decoding: buffer, as: Unicode.UTF8.self),
|
||||
"""
|
||||
# TYPE foo gauge
|
||||
|
||||
"""
|
||||
|
||||
+6
-7
@@ -1,4 +1,4 @@
|
||||
ARG swift_version=5.7
|
||||
ARG swift_version=5.8
|
||||
ARG ubuntu_version=jammy
|
||||
ARG base_image=swift:$swift_version-$ubuntu_version
|
||||
FROM $base_image
|
||||
@@ -26,9 +26,8 @@ RUN if [ "${ubuntu_version}" = "focal" ] ; then gem install jazzy; fi
|
||||
RUN mkdir -p $HOME/.tools
|
||||
RUN echo 'export PATH="$HOME/.tools:$PATH"' >> $HOME/.profile
|
||||
|
||||
# swiftformat (until part of the toolchain)
|
||||
|
||||
ARG swiftformat_version=0.48.8
|
||||
RUN git clone --branch $swiftformat_version --depth 1 https://github.com/nicklockwood/SwiftFormat $HOME/.tools/swift-format
|
||||
RUN cd $HOME/.tools/swift-format && swift build -c release
|
||||
RUN ln -s $HOME/.tools/swift-format/.build/release/swiftformat $HOME/.tools/swiftformat
|
||||
# swift-format (until part of the toolchain)
|
||||
RUN mkdir -p $HOME/.deps
|
||||
RUN git clone --branch release/$swift_version --depth 1 https://github.com/apple/swift-format $HOME/.deps/swift-format
|
||||
RUN cd $HOME/.deps/swift-format && swift build -c release
|
||||
RUN ln -s $HOME/.deps/swift-format/.build/release/swift-format $HOME/.tools
|
||||
|
||||
@@ -6,7 +6,8 @@ services:
|
||||
image: prometheus:22.04-5.9
|
||||
build:
|
||||
args:
|
||||
base_image: "swiftlang/swift:nightly-5.9-jammy"
|
||||
ubuntu_version: "jammy"
|
||||
swift_version: "5.9"
|
||||
|
||||
documentation-check:
|
||||
image: prometheus:22.04-5.9
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# this file is not designed to be run directly
|
||||
# instead, use the docker-compose.<os>.<swift> files
|
||||
# eg docker-compose -f docker/docker-compose.yaml -f docker/docker-compose.1804.50.yaml run test
|
||||
# eg docker-compose -f docker/docker-compose.yaml -f docker/docker-compose.2204.57.yaml run test
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
@@ -29,7 +29,7 @@ services:
|
||||
documentation-check:
|
||||
<<: *common
|
||||
command: /bin/bash -xcl "./scripts/check-docs.sh"
|
||||
|
||||
|
||||
test:
|
||||
<<: *common
|
||||
depends_on: [runtime-setup]
|
||||
|
||||
+8
-11
@@ -37,17 +37,14 @@ if git grep --color=never -i "${unacceptable_terms[@]}" > /dev/null; then
|
||||
fi
|
||||
printf "\033[0;32mokay.\033[0m\n"
|
||||
|
||||
#printf "=> Checking format... "
|
||||
#FIRST_OUT="$(git status --porcelain)"
|
||||
#swiftformat . > /dev/null 2>&1
|
||||
#SECOND_OUT="$(git status --porcelain)"
|
||||
#if [[ "$FIRST_OUT" != "$SECOND_OUT" ]]; then
|
||||
# printf "\033[0;31mformatting issues!\033[0m\n"
|
||||
# git --no-pager diff
|
||||
# exit 1
|
||||
#else
|
||||
# printf "\033[0;32mokay.\033[0m\n"
|
||||
#fi
|
||||
printf "=> Checking format... "
|
||||
output=$(swift-format lint --configuration .swift-format --recursive Sources Tests 2>&1) # Capture the command's output
|
||||
if [ -n "$output" ]; then
|
||||
printf "\033[0;31mformatting issues!\033[0m\n"
|
||||
exit 1
|
||||
else
|
||||
printf "\033[0;32mokay.\033[0m\n"
|
||||
fi
|
||||
|
||||
printf "=> Checking license headers\n"
|
||||
tmp=$(mktemp /tmp/.prometheus-soundness_XXXXXX)
|
||||
|
||||
Reference in New Issue
Block a user