Skip to content

Commit fed1d64

Browse files
committed
Add StrictConcurrency checks when possible
1 parent 87c0873 commit fed1d64

File tree

7 files changed

+101
-24
lines changed

7 files changed

+101
-24
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ let package = Package(
1313
targets: [
1414
.target(name: "OSLogLogger", dependencies: [
1515
.product(name: "Logging", package: "swift-log"),
16-
], path: "Sources"),
16+
], path: "Sources", exclude: ["OSLogLogger+WithSendable.swift"]),
1717
.testTarget(name: "OSLogLoggerTests", dependencies: ["OSLogLogger"], path: "Tests"),
1818
]
1919
)

[email protected]

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// swift-tools-version:5.8
2+
import PackageDescription
3+
4+
5+
//let swiftSettings: [SwiftSetting] = []
6+
let swiftSettings: [SwiftSetting] = [.enableExperimentalFeature("StrictConcurrency")]
7+
8+
let package = Package(
9+
name: "oslog-logger",
10+
products: [
11+
.library(name: "OSLogLogger", targets: ["OSLogLogger"])
12+
],
13+
dependencies: [
14+
.package(url: "https://github.com/apple/swift-log.git", from: "1.5.4"),
15+
],
16+
targets: [
17+
.target(name: "OSLogLogger", dependencies: [
18+
.product(name: "Logging", package: "swift-log"),
19+
], path: "Sources", exclude: ["OSLogLogger+NoSendable.swift"], swiftSettings: swiftSettings),
20+
.testTarget(name: "OSLogLoggerTests", dependencies: ["OSLogLogger"], path: "Tests", swiftSettings: swiftSettings),
21+
]
22+
)

Sources/DummySendable.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import Foundation
2+
import os
3+
4+
5+
#if swift(>=5.5)
6+
public protocol GHALogger_Sendable : Sendable {}
7+
#else
8+
public protocol GHALogger_Sendable {}
9+
#endif
10+
11+
@available(macOS 11.0, tvOS 14.0, iOS 14.0, watchOS 7.0, *)
12+
extension Logger : GHALogger_Sendable {}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import Foundation
2+
3+
import Logging
4+
5+
6+
7+
extension OSLogLogger {
8+
9+
/**
10+
Convenience init that splits the label in a subsystem and a category.
11+
12+
The format of the label should be as follow: "subsystem:category".
13+
The subsystem _should_ be a reverse-DNS identifier (as per Apple doc).
14+
Example: "`com.xcode-actions.oslog-logger:LogHandler`".
15+
16+
If there is no colon in the given label
17+
we set the category to “`<none>`” (it cannot be `nil`, surprisingly, and we decided against the empty String to be able to still filter this category)
18+
and we use the whole label for the subsystem.
19+
20+
It is _not_ possible to have a subsystem containing a colon using this initializer. */
21+
public init(label: String, metadataProvider: Logging.Logger.MetadataProvider? = LoggingSystem.metadataProvider) {
22+
let split = label.split(separator: ":", maxSplits: 1, omittingEmptySubsequences: false)
23+
let subsystem = split[0] /* Cannot not exists as we do not omit empty subsequences in the split. */
24+
let categoryCollection = split.dropFirst()
25+
assert(categoryCollection.count <= 1)
26+
27+
self.init(subsystem: String(subsystem), category: categoryCollection.first.flatMap(String.init) ?? "<none>", metadataProvider: metadataProvider)
28+
}
29+
30+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import Foundation
2+
3+
import Logging
4+
5+
6+
7+
/* The @Sendable attribute is only available starting at Swift 5.5.
8+
* We make these methods only available starting at Swift 5.8 for our convenience (avoids creating another Package@swift-... file)
9+
* and because for Swift <5.8 the non-@Sendable variants of the methods are available. */
10+
extension OSLogLogger {
11+
12+
/**
13+
Convenience init that splits the label in a subsystem and a category.
14+
15+
The format of the label should be as follow: "subsystem:category".
16+
The subsystem _should_ be a reverse-DNS identifier (as per Apple doc).
17+
Example: "`com.xcode-actions.oslog-logger:LogHandler`".
18+
19+
If there is no colon in the given label
20+
we set the category to “`<none>`” (it cannot be `nil`, surprisingly, and we decided against the empty String to be able to still filter this category)
21+
and we use the whole label for the subsystem.
22+
23+
It is _not_ possible to have a subsystem containing a colon using this initializer. */
24+
@Sendable
25+
public init(label: String, metadataProvider: Logging.Logger.MetadataProvider? = LoggingSystem.metadataProvider) {
26+
let split = label.split(separator: ":", maxSplits: 1, omittingEmptySubsequences: false)
27+
let subsystem = split[0] /* Cannot not exists as we do not omit empty subsequences in the split. */
28+
let categoryCollection = split.dropFirst()
29+
assert(categoryCollection.count <= 1)
30+
31+
self.init(subsystem: String(subsystem), category: categoryCollection.first.flatMap(String.init) ?? "<none>", metadataProvider: metadataProvider)
32+
}
33+
34+
}

Sources/OSLogLogger.swift

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,6 @@ public struct OSLogLogger : LogHandler {
1616
}
1717
public var metadataProvider: Logging.Logger.MetadataProvider?
1818

19-
/**
20-
Convenience init that splits the label in a subsystem and a category.
21-
22-
The format of the label should be as follow: "subsystem:category".
23-
The subsystem _should_ be a reverse-DNS identifier (as per Apple doc).
24-
Example: "`com.xcode-actions.oslog-logger:LogHandler`".
25-
26-
If there is no colon in the given label
27-
we set the category to “`<none>`” (it cannot be `nil`, surprisingly, and we decided against the empty String to be able to still filter this category)
28-
and we use the whole label for the subsystem.
29-
30-
It is _not_ possible to have a subsystem containing a colon using this initializer. */
31-
public init(label: String, metadataProvider: Logging.Logger.MetadataProvider? = LoggingSystem.metadataProvider) {
32-
let split = label.split(separator: ":", maxSplits: 1, omittingEmptySubsequences: false)
33-
let subsystem = split[0] /* Cannot not exists as we do not omit empty subsequences in the split. */
34-
let categoryCollection = split.dropFirst()
35-
assert(categoryCollection.count <= 1)
36-
37-
self.init(subsystem: String(subsystem), category: categoryCollection.first.flatMap(String.init) ?? "<none>", metadataProvider: metadataProvider)
38-
}
39-
4019
public init(subsystem: String, category: String, metadataProvider: Logging.Logger.MetadataProvider? = LoggingSystem.metadataProvider) {
4120
self.metadataProvider = metadataProvider
4221
if #available(macOS 11, tvOS 14, iOS 14, watchOS 7, *) {

Sources/UnderlyingLogger.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import os
99
*
1010
* Why not use OSLog everywhere?
1111
* Because it is broken (at least on macOS 14/iOS 17) and the subsystem and category are not properly set. */
12-
internal enum UnderlyingLogger {
12+
internal enum UnderlyingLogger : GHALogger_Sendable {
1313

1414
case oslog(OSLog)
15-
case logger(Any)
15+
case logger(GHALogger_Sendable)
1616

1717
var oslog: OSLog! {
1818
switch self {

0 commit comments

Comments
 (0)