Skip to content

Commit 5580757

Browse files
committed
new: FQMetricDescriptor overload option
Adds a new way to create metrics using an FQMetricDescriptor, which makes it easier to build metric names programmatically. The changes are fully backward compatible. Signed-off-by: Melissa Kilby <[email protected]>
1 parent ba92571 commit 5580757

File tree

5 files changed

+884
-0
lines changed

5 files changed

+884
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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+
/// Creates a new ``FQMetricDescriptor`` 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+
///
20+
/// - Warning: This initializer will trigger a `preconditionFailure` if ``metricName`` is an empty string.
21+
///
22+
/// - Parameter namespace: An optional top-level namespace for the metric.
23+
/// - Parameter subsystem: An optional subsystem to group related metrics within a namespace.
24+
/// - Parameter metricName: The required, descriptive base name of the metric.
25+
/// - Parameter unitName: An optional suffix describing the metric's unit (e.g., `_seconds`, `_total`).
26+
/// - Parameter helpText: Optional descriptive text for the metric.
27+
/// - Returns: A new ``FQMetricDescriptor`` instance with the specified components.
28+
public struct FQMetricDescriptor {
29+
public let namespace: String?
30+
public let subsystem: String?
31+
public let metricName: String
32+
public let unitName: String?
33+
public let helpText: String?
34+
35+
public init(
36+
namespace: String? = nil,
37+
subsystem: String? = nil,
38+
metricName: String,
39+
unitName: String? = nil,
40+
helpText: String? = nil
41+
) {
42+
precondition(!metricName.isEmpty, "metricName must not be empty")
43+
self.namespace = namespace
44+
self.subsystem = subsystem
45+
self.metricName = metricName
46+
self.unitName = unitName
47+
self.helpText = helpText
48+
}
49+
50+
public var name: String {
51+
[namespace, subsystem, metricName, unitName]
52+
.compactMap { $0?.isEmpty == false ? $0 : nil }
53+
.joined(separator: "_")
54+
}
55+
}

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 ``FQMetricDescriptor`` that provides the fully qualified name for the metric.
103+
/// - Returns: A ``Counter`` that is registered with this ``PrometheusCollectorRegistry``
104+
public func makeCounter(descriptor: FQMetricDescriptor) -> 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 ``FQMetricDescriptor`` 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: FQMetricDescriptor, 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 ``FQMetricDescriptor`` that provides the fully qualified name for the metric.
214+
/// - Returns: A ``Gauge`` that is registered with this ``PrometheusCollectorRegistry``
215+
public func makeGauge(descriptor: FQMetricDescriptor) -> 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 ``FQMetricDescriptor`` 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: FQMetricDescriptor, 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 ``FQMetricDescriptor`` 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: FQMetricDescriptor, 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 ``FQMetricDescriptor`` 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: FQMetricDescriptor,
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 ``FQMetricDescriptor`` 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: FQMetricDescriptor, 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 ``FQMetricDescriptor`` 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: FQMetricDescriptor,
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)