Skip to content

Commit 96d854f

Browse files
incertumktoso
andcommitted
update: apply reviewers suggestions
More precise thread-safety guidance / documentation. Fix Swift Docc checks. Co-authored-by: Konrad `ktoso` Malawski <[email protected]> Signed-off-by: Melissa Kilby <[email protected]>
1 parent 8e837ac commit 96d854f

File tree

4 files changed

+28
-33
lines changed

4 files changed

+28
-33
lines changed

Sources/Prometheus/Docs.docc/index.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ A prometheus client library for Swift.
99
#### Key Features
1010

1111
- *Standards Compliant*: Follows Prometheus naming conventions and exposition formats, enforces base guarantees.
12-
- *Type Safe*: Prevents common configuration errors through Swift's type system.
13-
- *Thread Safe*: Operations use internal locking and conform to `Sendable`.
1412
- *Flexible Metric Labeling*: Supports flexible metric label structures with consistency guarantees.
15-
- *Swift Metrics Compatible*: Use the native Prometheus client API implemented in this library or integrate with [Swift Metrics](doc:swift-metrics).
13+
- *Thread Safe and Type-Safe*.
14+
- *Swift Metrics Compatible*: Use the native Prometheus client API implemented in this library or use [Swift Metrics](doc:swift-metrics) as a backend for this library.
1615

1716
For general Prometheus guidance, see the [Prometheus Documentation][prometheus-docs].
1817

Sources/Prometheus/Docs.docc/labels.md

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Create, register, update, and expose metrics for Prometheus.
44

5-
## Touring a Practical Example
5+
## Overview
66

77
Create multiple collectors that are associated with a specific `PrometheusCollectorRegistry()` instance.
88

@@ -113,7 +113,7 @@ myapp_http_request_duration_seconds_count 1
113113
myapp_system_memory_usage_bytes 134217728.0
114114
```
115115

116-
Notice how:
116+
### Notice how:
117117

118118
*Metadata Deduplication:*
119119
- Each metric name gets exactly one `# HELP` and `# TYPE` line (before the metric output), regardless of how many label variations exist.
@@ -137,13 +137,17 @@ Notice how:
137137

138138
*Prometheus Compliance:*
139139
- Metric names, label names, and `# HELP` text are validated against Prometheus character allowlists.
140-
- Different label names and structures are allowed for the same metric name.
141-
- However, cannot mix labeled and unlabeled metrics with the same name.
140+
- Different label names and structures are allowed for the same metric name; however, cannot mix labeled and unlabeled metrics with the same metric name.
142141
- Must use consistent metric types, help text, and histogram buckets for the same metric name.
143142

144143
*Known Limitations:*
145144
- Prometheus converts all metrics to floating-point types, which can cause precision loss. For example, Counters designed for `UInt64` values or Gauges capturing nanosecond timestamps will lose precision. In such cases, consider alternative frameworks or solutions.
146145

146+
*Thread-safe through multiple mechanisms:*
147+
- Metric value updates are based on atomic operations.
148+
- Export functions like `emitToBuffer()` and `emitToString()` use internal locking and conform to Swift [Sendable](https://developer.apple.com/documentation/Swift/Sendable).
149+
- Lower-level export via `emit(into:)` is thread-safe due to Swift's `inout` [exclusivity](https://www.swift.org/blog/swift-5-exclusivity/) guarantees, with the compiler preventing concurrent access through warnings (Swift 5) or errors (Swift 6 [strict concurrency](https://developer.apple.com/documentation/swift/adoptingswift6) mode).
150+
147151
*Correct Labels Usage:*
148152

149153
```swift
@@ -197,17 +201,11 @@ let goodCounter1 = registry.makeCounter(name: "requests_total", labels: [("metho
197201
let goodCounter2 = registry.makeCounter(name: "requests_total", labels: [("endpoint", "/api/users")]) // Meaningful dimensions
198202
```
199203

200-
## Thread Safety
201-
202-
All operations are thread-safe, with the exception of the lower-level ``emit(into:)`` overload variant (compared to the thread-safe ``emitToBuffer()`` or ``emitToString()``). The client uses internal locking to ensure consistency across concurrent access and conforms to Swift's `Sendable` protocol, meaning it can be safely passed between actors and used in concurrent contexts without additional synchronization.
203-
204-
## Additional Notes
204+
*Additional Notes*:
205205

206-
Above, we demonstrated the Prometheus’s proper approach. However, you can also integrate with the `swift-metrics` ecosystem using `PrometheusMetricsFactory`.
206+
Above, we demonstrated the Prometheus’s proper approach. However, you can also use [Swift Metrics](doc:swift-metrics) as a backend for this library via `PrometheusMetricsFactory`.
207207

208-
- <doc:swift-metrics>
209-
210-
> Note: The naming between Prometheus and Swift-Metrics is a bit confusing. Swift Metrics calls a
208+
> Note: The naming between Prometheus and Swift-Metrics may be confusing. Swift Metrics calls a
211209
> metric's name its label and they call a metric's labels dimensions. In this article, when we
212210
> refer to labels, we mean the additional properties that can be added to a metrics name.
213211
>
@@ -216,17 +214,18 @@ Above, we demonstrated the Prometheus’s proper approach. However, you can also
216214
> | swift-metrics | `label` | `dimensions` |
217215
> | Prometheus | `name` | `labels` |
218216
219-
220-
## References
217+
### References
221218

222219
- Prometheus [Docs - Overview][prometheus-docs]
223220
- Prometheus [Instrumentation Best Practices - Use Labels][prometheus-use-labels]
221+
- Prometheus [Naming Best Practices][prometheus-naming]
224222
- Prometheus [Client Library Guidelines][prometheus-client-libs]
225223
- Prometheus [Exporter Guidelines][prometheus-exporters]
226224
- Prometheus [Exposition Format][prometheus-exposition]
227225

228226
[prometheus-docs]: https://prometheus.io/docs/introduction/overview/
229227
[prometheus-use-labels]: https://prometheus.io/docs/practices/instrumentation/#use-labels
228+
[prometheus-naming]: https://prometheus.io/docs/practices/naming/
230229
[prometheus-client-libs]: https://prometheus.io/docs/instrumenting/writing_clientlibs/
231230
[prometheus-exporters]: https://prometheus.io/docs/instrumenting/writing_exporters/
232231
[prometheus-exposition]: https://prometheus.io/docs/instrumenting/exposition_formats/

Sources/Prometheus/Docs.docc/swift-metrics.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
# Integrate with Swift Metrics
1+
# Swift Metrics as Backend
22

3-
Learn how Swift Prometheus integrates with Swift Metrics – an abstract API that is widely used in
4-
the swift-server ecosystem.
3+
Learn how to use Swift Metrics as a backend for Swift Prometheus.
54

65
## Overview
76

@@ -51,12 +50,12 @@ func main() {
5150
}
5251
```
5352

54-
## Modifying the Prometheus Export
53+
### Modifying the Prometheus Export
5554

5655
Now that we have setup the Prometheus export, lets discuss which configuration options there are to
5756
modify the Swift Metrics export.
5857

59-
### Using a specific Collector Registry as the Export Target
58+
#### Using a specific Collector Registry as the Export Target
6059

6160
If you create a `PrometheusMetricsFactory()` without specifying a ``PrometheusCollectorRegistry``,
6261
it will use ``PrometheusMetricsFactory/defaultRegistry`` as the underlying collector registry.
@@ -78,7 +77,7 @@ factory.registry = registry
7877
MetricsSystem.bootstrap(factory)
7978
```
8079

81-
### Modifying Swift metrics names and labels
80+
#### Modifying Swift metrics names and labels
8281

8382
When you create a ``PrometheusMetricsFactory``, you can also set the
8483
``PrometheusMetricsFactory/nameAndLabelSanitizer`` to modify the metric names and labels:
@@ -107,9 +106,9 @@ generated in a third party library.
107106
> Use the ``PrometheusMetricsFactory/nameAndLabelSanitizer`` to ensure this remains true metrics
108107
> that are created in third party libraries. See <doc:labels> for more information about this.
109108
110-
### Defining Buckets for Histograms
109+
#### Defining Buckets for Histograms
111110

112-
#### Default buckets
111+
Default buckets:
113112

114113
Swift Metric `Timer`s are backed by a Prometheus ``DurationHistogram`` and Swift Metric
115114
`Recorder`s that aggregate are backed by a Prometheus ``ValueHistogram``. As a user, you can
@@ -141,7 +140,7 @@ Timer(label: "my_timer") // will use the buckets specified in `defaultDurationHi
141140
Recorder(label: "my_recorder", aggregate: true) // will use the buckets specified in `defaultValueHistogramBuckets`
142141
```
143142

144-
#### Buckets by name
143+
Buckets by name:
145144

146145
You can also specify the buckets by metric name:
147146

Sources/Prometheus/PrometheusCollectorRegistry.swift

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,7 @@ public final class PrometheusCollectorRegistry: Sendable {
943943
/// This is useful when the registry's metric composition has changed significantly and you want to
944944
/// optimize buffer size for the new workload.
945945
///
946-
/// - Note: Thread-safe. Does not affect ``emit(into:)`` calls which use external buffers
946+
/// - Note: Does not affect ``emit(into:)`` calls which use external buffers
947947
public func resetInternalBuffer() {
948948
bufferBox.withLockedValue { buffer in
949949
// Resets capacity to 0, forcing re-calibration
@@ -958,7 +958,7 @@ public final class PrometheusCollectorRegistry: Sendable {
958958
/// the registry's output requirements increase.
959959
///
960960
/// - Returns: The current buffer capacity in bytes
961-
/// - Note: Thread-safe. Primarily useful for testing and monitoring buffer behavior
961+
/// - Note: Primarily useful for testing and monitoring buffer behavior
962962
public func internalBufferCapacity() -> Int {
963963
return bufferBox.withLockedValue { buffer in
964964
buffer.capacity
@@ -972,7 +972,7 @@ public final class PrometheusCollectorRegistry: Sendable {
972972
/// established capacity, clearing content but preserving the initially allocated memory.
973973
///
974974
/// - Returns: A String containing all registered metrics in Prometheus text format
975-
/// - Note: Thread-safe. Use ``resetInternalBuffer()`` to force recalibration
975+
/// - Note: Use ``resetInternalBuffer()`` to force recalibration
976976
/// - SeeAlso: ``emitToBuffer()`` for raw UTF-8 bytes, ``emit(into:)`` for custom buffer
977977
public func emitToString() -> String {
978978
return bufferBox.withLockedValue { buffer in
@@ -995,7 +995,7 @@ public final class PrometheusCollectorRegistry: Sendable {
995995
/// established capacity, clearing content but preserving the initially allocated memory. Returns a copy.
996996
///
997997
/// - Returns: A copy of the UTF-8 encoded byte array containing all registered metrics
998-
/// - Note: Thread-safe. Use ``resetInternalBuffer()`` to force recalibration
998+
/// - Note: Use ``resetInternalBuffer()`` to force recalibration
999999
/// - SeeAlso: ``emitToString()`` for String output, ``emit(into:)`` for custom buffer
10001000
public func emitToBuffer() -> [UInt8] {
10011001
return bufferBox.withLockedValue { buffer in
@@ -1016,8 +1016,6 @@ public final class PrometheusCollectorRegistry: Sendable {
10161016
/// performance and control but requires manual buffer lifecycle management.
10171017
///
10181018
/// - Parameter buffer: The buffer to write metrics data into. Content will be appended to existing data
1019-
/// - Note: Not thread-safe. Caller must handle synchronization and may optimize buffer capacity for
1020-
/// maximum performance by reducing reallocations
10211019
/// - SeeAlso: ``emitToString()`` and ``emitToBuffer()`` for automatic buffer management
10221020
public func emit(into buffer: inout [UInt8]) {
10231021
let metrics = self.box.withLockedValue { $0 }

0 commit comments

Comments
 (0)