Skip to content

Commit b546409

Browse files
incertumktoso
andauthored
new: FQMetricDescriptor overload option (#126)
Co-authored-by: Konrad `ktoso` Malawski <[email protected]>
1 parent 0fb8c6d commit b546409

File tree

5 files changed

+893
-0
lines changed

5 files changed

+893
-0
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftPrometheus open source project
4+
//
5+
// Copyright (c) 2018-2025 SwiftPrometheus project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftPrometheus project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
/// A descriptor that defines the components of a fully qualified Prometheus metric name.
16+
///
17+
/// The final, underscore-separated metric name is generated by the ``name`` computed property. The ``helpText``
18+
/// is used to generate the corresponding `# HELP` line in the Prometheus exposition format.
19+
/// - Warning: This initializer will trigger a `preconditionFailure` if ``metricName`` is an empty string.
20+
public struct MetricNameDescriptor {
21+
/// An optional top-level namespace for the metric.
22+
public let namespace: String?
23+
24+
/// An optional subsystem to group related metrics.
25+
public let subsystem: String?
26+
27+
/// The required, descriptive base name of the metric.
28+
public let metricName: String
29+
30+
/// An optional suffix describing the metric's unit (e.g., `total`).
31+
public let unitName: String?
32+
33+
/// Optional descriptive text for the metric.
34+
public let helpText: String?
35+
36+
/// Creates a new ``MetricNameDescriptor`` that defines the components of a fully qualified Prometheus metric name.
37+
///
38+
/// - Parameter namespace: An optional top-level namespace for the metric.
39+
/// - Parameter subsystem: An optional subsystem to group related metrics within a namespace.
40+
/// - Parameter metricName: The required, descriptive base name of the metric.
41+
/// - Parameter unitName: An optional suffix describing the metric's unit (e.g., `total`).
42+
/// - Parameter helpText: Optional descriptive text for the metric.
43+
public init(
44+
namespace: String? = nil,
45+
subsystem: String? = nil,
46+
metricName: String,
47+
unitName: String? = nil,
48+
helpText: String? = nil
49+
) {
50+
precondition(!metricName.isEmpty, "metricName must not be empty")
51+
self.namespace = namespace
52+
self.subsystem = subsystem
53+
self.metricName = metricName
54+
self.unitName = unitName
55+
self.helpText = helpText
56+
}
57+
58+
/// The fully qualified metric name, joining non-empty components with underscores.
59+
public var name: String {
60+
[namespace, subsystem, metricName, unitName]
61+
.compactMap { $0?.isEmpty == false ? $0 : nil }
62+
.joined(separator: "_")
63+
}
64+
}

Sources/Prometheus/PrometheusCollectorRegistry.swift

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,18 @@ public final class PrometheusCollectorRegistry: Sendable {
9393
}
9494
}
9595

96+
/// Creates a new ``Counter`` collector or returns the already existing one with the same name,
97+
/// based on the provided descriptor.
98+
///
99+
/// When the ``PrometheusCollectorRegistry/emit(into:)`` is called, metrics from the
100+
/// created ``Counter`` will be part of the export.
101+
///
102+
/// - Parameter descriptor: An ``MetricNameDescriptor`` that provides the fully qualified name for the metric.
103+
/// - Returns: A ``Counter`` that is registered with this ``PrometheusCollectorRegistry``
104+
public func makeCounter(descriptor: MetricNameDescriptor) -> Counter {
105+
return self.makeCounter(name: descriptor.name)
106+
}
107+
96108
/// Creates a new ``Counter`` collector or returns the already existing one with the same name.
97109
///
98110
/// When the ``PrometheusCollectorRegistry/emit(into:)`` is called, metrics from the
@@ -150,6 +162,20 @@ public final class PrometheusCollectorRegistry: Sendable {
150162
}
151163
}
152164

165+
/// Creates a new ``Counter`` collector or returns the already existing one with the same name,
166+
/// based on the provided descriptor.
167+
///
168+
/// When the ``PrometheusCollectorRegistry/emit(into:)`` is called, metrics from the
169+
/// created ``Counter`` will be part of the export.
170+
///
171+
/// - Parameter descriptor: An ``MetricNameDescriptor`` that provides the fully qualified name for the metric.
172+
/// - Parameter labels: Labels are sets of key-value pairs that allow us to characterize and organize
173+
/// what’s actually being measured in a Prometheus metric.
174+
/// - Returns: A ``Counter`` that is registered with this ``PrometheusCollectorRegistry``
175+
public func makeCounter(descriptor: MetricNameDescriptor, labels: [(String, String)]) -> Counter {
176+
return self.makeCounter(name: descriptor.name, labels: labels)
177+
}
178+
153179
/// Creates a new ``Gauge`` collector or returns the already existing one with the same name.
154180
///
155181
/// When the ``PrometheusCollectorRegistry/emit(into:)`` is called, metrics from the
@@ -178,6 +204,18 @@ public final class PrometheusCollectorRegistry: Sendable {
178204
}
179205
}
180206

207+
/// Creates a new ``Gauge`` collector or returns the already existing one with the same name,
208+
/// based on the provided descriptor.
209+
///
210+
/// When the ``PrometheusCollectorRegistry/emit(into:)`` is called, metrics from the
211+
/// created ``Gauge`` will be part of the export.
212+
///
213+
/// - Parameter descriptor: An ``MetricNameDescriptor`` that provides the fully qualified name for the metric.
214+
/// - Returns: A ``Gauge`` that is registered with this ``PrometheusCollectorRegistry``
215+
public func makeGauge(descriptor: MetricNameDescriptor) -> Gauge {
216+
return self.makeGauge(name: descriptor.name)
217+
}
218+
181219
/// Creates a new ``Gauge`` collector or returns the already existing one with the same name.
182220
///
183221
/// When the ``PrometheusCollectorRegistry/emit(into:)`` is called, metrics from the
@@ -235,6 +273,20 @@ public final class PrometheusCollectorRegistry: Sendable {
235273
}
236274
}
237275

276+
/// Creates a new ``Gauge`` collector or returns the already existing one with the same name and labels,
277+
/// based on the provided descriptor.
278+
///
279+
/// When the ``PrometheusCollectorRegistry/emit(into:)`` is called, metrics from the
280+
/// created ``Gauge`` will be part of the export.
281+
///
282+
/// - Parameter descriptor: An ``MetricNameDescriptor`` that provides the fully qualified name for the metric.
283+
/// - Parameter labels: Labels are sets of key-value pairs that allow us to characterize and organize
284+
/// what’s actually being measured in a Prometheus metric.
285+
/// - Returns: A ``Gauge`` that is registered with this ``PrometheusCollectorRegistry``
286+
public func makeGauge(descriptor: MetricNameDescriptor, labels: [(String, String)]) -> Gauge {
287+
return self.makeGauge(name: descriptor.name, labels: labels)
288+
}
289+
238290
/// Creates a new ``DurationHistogram`` collector or returns the already existing one with the same name.
239291
///
240292
/// When the ``PrometheusCollectorRegistry/emit(into:)`` is called, metrics from the
@@ -264,6 +316,19 @@ public final class PrometheusCollectorRegistry: Sendable {
264316
}
265317
}
266318

319+
/// Creates a new ``DurationHistogram`` collector or returns the already existing one with the same name,
320+
/// based on the provided descriptor.
321+
///
322+
/// When the ``PrometheusCollectorRegistry/emit(into:)`` is called, metrics from the
323+
/// created ``DurationHistogram`` will be part of the export.
324+
///
325+
/// - Parameter descriptor: An ``MetricNameDescriptor`` that provides the fully qualified name for the metric.
326+
/// - Parameter buckets: Define the buckets that shall be used within the ``DurationHistogram``
327+
/// - Returns: A ``DurationHistogram`` that is registered with this ``PrometheusCollectorRegistry``
328+
public func makeDurationHistogram(descriptor: MetricNameDescriptor, buckets: [Duration]) -> DurationHistogram {
329+
return self.makeDurationHistogram(name: descriptor.name, buckets: buckets)
330+
}
331+
267332
/// Creates a new ``DurationHistogram`` collector or returns the already existing one with the same name.
268333
///
269334
/// When the ``PrometheusCollectorRegistry/emit(into:)`` is called, metrics from the
@@ -338,6 +403,25 @@ public final class PrometheusCollectorRegistry: Sendable {
338403
}
339404
}
340405

406+
/// Creates a new ``DurationHistogram`` collector or returns the already existing one with the same name and labels,
407+
/// based on the provided descriptor.
408+
///
409+
/// When the ``PrometheusCollectorRegistry/emit(into:)`` is called, metrics from the
410+
/// created ``DurationHistogram`` will be part of the export.
411+
///
412+
/// - Parameter descriptor: An ``MetricNameDescriptor`` that provides the fully qualified name for the metric.
413+
/// - Parameter labels: Labels are sets of key-value pairs that allow us to characterize and organize
414+
/// what’s actually being measured in a Prometheus metric.
415+
/// - Parameter buckets: Define the buckets that shall be used within the ``DurationHistogram``
416+
/// - Returns: A ``DurationHistogram`` that is registered with this ``PrometheusCollectorRegistry``
417+
public func makeDurationHistogram(
418+
descriptor: MetricNameDescriptor,
419+
labels: [(String, String)],
420+
buckets: [Duration]
421+
) -> DurationHistogram {
422+
return self.makeDurationHistogram(name: descriptor.name, labels: labels, buckets: buckets)
423+
}
424+
341425
/// Creates a new ``ValueHistogram`` collector or returns the already existing one with the same name.
342426
///
343427
/// When the ``PrometheusCollectorRegistry/emit(into:)`` is called, metrics from the
@@ -362,6 +446,19 @@ public final class PrometheusCollectorRegistry: Sendable {
362446
}
363447
}
364448

449+
/// Creates a new ``ValueHistogram`` collector or returns the already existing one with the same name,
450+
/// based on the provided descriptor.
451+
///
452+
/// When the ``PrometheusCollectorRegistry/emit(into:)`` is called, metrics from the
453+
/// created ``ValueHistogram`` will be part of the export.
454+
///
455+
/// - Parameter descriptor: An ``MetricNameDescriptor`` that provides the fully qualified name for the metric.
456+
/// - Parameter buckets: Define the buckets that shall be used within the ``ValueHistogram``
457+
/// - Returns: A ``ValueHistogram`` that is registered with this ``PrometheusCollectorRegistry``
458+
public func makeValueHistogram(descriptor: MetricNameDescriptor, buckets: [Double]) -> ValueHistogram {
459+
return self.makeValueHistogram(name: descriptor.name, buckets: buckets)
460+
}
461+
365462
/// Creates a new ``ValueHistogram`` collector or returns the already existing one with the same name.
366463
///
367464
/// When the ``PrometheusCollectorRegistry/emit(into:)`` is called, metrics from the
@@ -408,6 +505,27 @@ public final class PrometheusCollectorRegistry: Sendable {
408505
}
409506
}
410507

508+
/// Creates a new ``ValueHistogram`` collector or returns the already existing one with the same name and labels,
509+
/// based on the provided descriptor.
510+
///
511+
/// When the ``PrometheusCollectorRegistry/emit(into:)`` is called, metrics from the
512+
/// created ``ValueHistogram`` will be part of the export.
513+
///
514+
/// - Parameter descriptor: An ``MetricNameDescriptor`` that provides the fully qualified name for the metric.
515+
/// - Parameter labels: Labels are sets of key-value pairs that allow us to characterize and organize
516+
/// what’s actually being measured in a Prometheus metric.
517+
/// - Parameter buckets: Define the buckets that shall be used within the ``ValueHistogram``
518+
/// - Returns: A ``ValueHistogram`` that is registered with this ``PrometheusCollectorRegistry``
519+
public func makeValueHistogram(
520+
descriptor: MetricNameDescriptor,
521+
labels: [(String, String)],
522+
buckets: [Double]
523+
) -> ValueHistogram {
524+
return self.makeValueHistogram(name: descriptor.name, labels: labels, buckets: buckets)
525+
}
526+
527+
// MARK: - Histogram
528+
411529
// MARK: Destroying Metrics
412530

413531
/// Unregisters a ``Counter`` from the ``PrometheusCollectorRegistry``. This means that the provided ``Counter``

0 commit comments

Comments
 (0)