Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make logging optional and update docs #189

Merged
merged 7 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ Furthermore, the group will setup signal listeners for the configured signals an
on each service.

```swift
import ServiceLifecycle
import Logging

actor FooService: Service {
func run() async throws {
print("FooService starting")
Expand All @@ -72,19 +75,21 @@ actor FooService: Service {

@main
struct Application {
static let logger = Logger(label: "Application")

static func main() async throws {
let service1 = FooService()
let service2 = FooService()

let serviceGroup = ServiceGroup(
services: [service1, service2],
configuration: .init(gracefulShutdownSignals: [.sigterm]),
gracefulShutdownSignals: [.sigterm],
logger: logger
)

try await serviceGroup.run()
}
}

```

## Security
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,7 @@ struct Application {

let serviceGroup = ServiceGroup(
// We are encoding the dependency hierarchy here by listing the fooService first
configuration: .init(
services: [
.init(service: fooService),
.init(service: barService)
],
logger: logger
),
services: [fooService, barService]
)

try await serviceGroup.run()
Expand Down Expand Up @@ -148,11 +142,8 @@ struct Application {
})

let serviceGroup = ServiceGroup(
configuration: .init(
services: [.init(service: streamingService)],
gracefulShutdownSignals: [.sigterm],
logger: logger
)
services: [streamingService],
gracefulShutdownSignals: [.sigterm]
)

try await serviceGroup.run()
Expand Down Expand Up @@ -210,11 +201,8 @@ struct Application {
})

let serviceGroup = ServiceGroup(
configuration: .init(
services: [.init(service: streamingService)],
gracefulShutdownSignals: [.sigterm],
logger: logger
)
services: [streamingService],
gracefulShutdownSignals: [.sigterm]
)

try await serviceGroup.run()
Expand Down Expand Up @@ -266,8 +254,7 @@ struct Application {
successTerminationBehavior: .shutdownGracefully,
failureTerminationBehavior: .shutdownGracefully
)
],
logger: logger
]
),
)

Expand Down
68 changes: 34 additions & 34 deletions Sources/ServiceLifecycle/ServiceGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public actor ServiceGroup: Sendable, Service {
}

/// The logger.
private let logger: Logger
private let logger: Logger?
/// The logging configuration.
private let loggingConfiguration: ServiceGroupConfiguration.LoggingConfiguration
/// The maximum amount of time that graceful shutdown is allowed to take.
Expand All @@ -55,7 +55,7 @@ public actor ServiceGroup: Sendable, Service {
Set(configuration.gracefulShutdownSignals).isDisjoint(with: configuration.cancellationSignals),
"Overlapping graceful shutdown and cancellation signals"
)
precondition(configuration.logger.label != deprecatedLoggerLabel, "Please migrate to the new initializers")
precondition(configuration.logger?.label != deprecatedLoggerLabel, "Please migrate to the new initializers")
self.state = .initial(services: configuration.services)
self.gracefulShutdownSignals = configuration.gracefulShutdownSignals
self.cancellationSignals = configuration.cancellationSignals
Expand All @@ -76,7 +76,7 @@ public actor ServiceGroup: Sendable, Service {
services: [any Service],
gracefulShutdownSignals: [UnixSignal] = [],
cancellationSignals: [UnixSignal] = [],
logger: Logger
logger: Logger? = nil
) {
let configuration = ServiceGroupConfiguration(
services: services.map { ServiceGroupConfiguration.ServiceConfiguration(service: $0) },
Expand All @@ -88,7 +88,7 @@ public actor ServiceGroup: Sendable, Service {
self.init(configuration: configuration)
}

@available(*, deprecated)
@available(*, deprecated, renamed: "init(services:gracefulShutdownSignals:cancellationSignals:logger:)")
public init(
services: [any Service],
configuration: ServiceGroupConfiguration,
Expand Down Expand Up @@ -204,7 +204,7 @@ public actor ServiceGroup: Sendable, Service {
services: inout [ServiceGroupConfiguration.ServiceConfiguration],
gracefulShutdownStream: AsyncStream<Void>
) async throws {
self.logger.debug(
self.logger?.debug(
"Starting service lifecycle",
metadata: [
self.loggingConfiguration.keys.gracefulShutdownSignalsKey: "\(self.gracefulShutdownSignals)",
Expand Down Expand Up @@ -270,7 +270,7 @@ public actor ServiceGroup: Sendable, Service {
gracefulShutdownManagers.reserveCapacity(services.count)

for (index, serviceConfiguration) in services.enumerated() {
self.logger.debug(
self.logger?.debug(
"Starting service",
metadata: [
self.loggingConfiguration.keys.serviceKey: "\(serviceConfiguration.service)"
Expand Down Expand Up @@ -324,7 +324,7 @@ public actor ServiceGroup: Sendable, Service {

switch service.successTerminationBehavior.behavior {
case .cancelGroup:
self.logger.debug(
self.logger?.debug(
"Service finished unexpectedly. Cancelling group.",
metadata: [
self.loggingConfiguration.keys.serviceKey: "\(service.service)"
Expand All @@ -337,7 +337,7 @@ public actor ServiceGroup: Sendable, Service {
return .failure(ServiceGroupError.serviceFinishedUnexpectedly())

case .gracefullyShutdownGroup:
self.logger.debug(
self.logger?.debug(
"Service finished. Gracefully shutting down group.",
metadata: [
self.loggingConfiguration.keys.serviceKey: "\(service.service)"
Expand All @@ -357,7 +357,7 @@ public actor ServiceGroup: Sendable, Service {
}

case .ignore:
self.logger.debug(
self.logger?.debug(
"Service finished.",
metadata: [
self.loggingConfiguration.keys.serviceKey: "\(service.service)"
Expand All @@ -366,7 +366,7 @@ public actor ServiceGroup: Sendable, Service {
services[index] = nil

if services.allSatisfy({ $0 == nil }) {
self.logger.debug(
self.logger?.debug(
"All services finished."
)
self.cancelGroupAndSpawnTimeoutIfNeeded(
Expand All @@ -380,7 +380,7 @@ public actor ServiceGroup: Sendable, Service {
case .serviceThrew(let service, let index, let serviceError):
switch service.failureTerminationBehavior.behavior {
case .cancelGroup:
self.logger.debug(
self.logger?.debug(
"Service threw error. Cancelling group.",
metadata: [
self.loggingConfiguration.keys.serviceKey: "\(service.service)",
Expand All @@ -394,7 +394,7 @@ public actor ServiceGroup: Sendable, Service {
return .failure(serviceError)

case .gracefullyShutdownGroup:
self.logger.debug(
self.logger?.debug(
"Service threw error. Shutting down group.",
metadata: [
self.loggingConfiguration.keys.serviceKey: "\(service.service)",
Expand All @@ -416,7 +416,7 @@ public actor ServiceGroup: Sendable, Service {
}

case .ignore:
self.logger.debug(
self.logger?.debug(
"Service threw error.",
metadata: [
self.loggingConfiguration.keys.serviceKey: "\(service.service)",
Expand All @@ -426,7 +426,7 @@ public actor ServiceGroup: Sendable, Service {
services[index] = nil

if services.allSatisfy({ $0 == nil }) {
self.logger.debug(
self.logger?.debug(
"All services finished."
)

Expand All @@ -441,7 +441,7 @@ public actor ServiceGroup: Sendable, Service {
case .signalCaught(let unixSignal):
if self.gracefulShutdownSignals.contains(unixSignal) {
// Let's initiate graceful shutdown.
self.logger.debug(
self.logger?.debug(
"Signal caught. Shutting down the group.",
metadata: [
self.loggingConfiguration.keys.signalKey: "\(unixSignal)"
Expand All @@ -460,7 +460,7 @@ public actor ServiceGroup: Sendable, Service {
}
} else {
// Let's cancel the group.
self.logger.debug(
self.logger?.debug(
"Signal caught. Cancelling the group.",
metadata: [
self.loggingConfiguration.keys.signalKey: "\(unixSignal)"
Expand All @@ -475,7 +475,7 @@ public actor ServiceGroup: Sendable, Service {

case .gracefulShutdownCaught:
// We got a manual or inherited graceful shutdown. Let's initiate graceful shutdown.
self.logger.debug("Graceful shutdown caught. Cascading shutdown to services")
self.logger?.debug("Graceful shutdown caught. Cascading shutdown to services")

do {
try await self.shutdownGracefully(
Expand All @@ -492,7 +492,7 @@ public actor ServiceGroup: Sendable, Service {
case .cancellationCaught:
// We caught cancellation in our child task so we have to spawn
// our cancellation timeout task if needed
self.logger.debug("Caught cancellation.")
self.logger?.debug("Caught cancellation.")
self.cancelGroupAndSpawnTimeoutIfNeeded(
group: &group,
cancellationTimeoutTask: &cancellationTimeoutTask
Expand All @@ -517,7 +517,7 @@ public actor ServiceGroup: Sendable, Service {
return .success(())
}

self.logger.debug(
self.logger?.debug(
"Service lifecycle ended"
)
cancellationTimeoutTask?.cancel()
Expand Down Expand Up @@ -558,12 +558,12 @@ public actor ServiceGroup: Sendable, Service {
.enumerated().reversed()
{
guard let service = services[gracefulShutdownIndex] else {
self.logger.debug(
self.logger?.debug(
"Service already finished. Skipping shutdown"
)
continue gracefulShutdownLoop
}
self.logger.debug(
self.logger?.debug(
"Triggering graceful shutdown for service",
metadata: [
self.loggingConfiguration.keys.serviceKey: "\(service.service)"
Expand All @@ -583,7 +583,7 @@ public actor ServiceGroup: Sendable, Service {

guard index == gracefulShutdownIndex else {
// Another service exited unexpectedly
self.logger.debug(
self.logger?.debug(
"Service finished unexpectedly during graceful shutdown. Cancelling all other services now",
metadata: [
self.loggingConfiguration.keys.serviceKey: "\(service.service)"
Expand All @@ -598,7 +598,7 @@ public actor ServiceGroup: Sendable, Service {
}
// The service that we signalled graceful shutdown did exit/
// We can continue to the next one.
self.logger.debug(
self.logger?.debug(
"Service finished",
metadata: [
self.loggingConfiguration.keys.serviceKey: "\(service.service)"
Expand All @@ -610,7 +610,7 @@ public actor ServiceGroup: Sendable, Service {
services[index] = nil
switch service.failureTerminationBehavior.behavior {
case .cancelGroup:
self.logger.debug(
self.logger?.debug(
"Service threw error during graceful shutdown. Cancelling group.",
metadata: [
self.loggingConfiguration.keys.serviceKey: "\(service.service)",
Expand All @@ -628,7 +628,7 @@ public actor ServiceGroup: Sendable, Service {
guard index == gracefulShutdownIndex else {
// Another service threw while we were waiting for a shutdown
// We have to continue the iterating the task group's result
self.logger.debug(
self.logger?.debug(
"Another service than the service that we were shutting down threw. Continuing with the next one.",
metadata: [
self.loggingConfiguration.keys.serviceKey: "\(service.service)",
Expand All @@ -639,7 +639,7 @@ public actor ServiceGroup: Sendable, Service {
}
// The service that we were shutting down right now threw. Since it's failure
// behaviour is to shutdown the group we can continue
self.logger.debug(
self.logger?.debug(
"The service that we were shutting down threw. Continuing with the next one.",
metadata: [
self.loggingConfiguration.keys.serviceKey: "\(service.service)",
Expand All @@ -652,7 +652,7 @@ public actor ServiceGroup: Sendable, Service {
guard index == gracefulShutdownIndex else {
// Another service threw while we were waiting for a shutdown
// We have to continue the iterating the task group's result
self.logger.debug(
self.logger?.debug(
"Another service than the service that we were shutting down threw. Continuing with the next one.",
metadata: [
self.loggingConfiguration.keys.serviceKey: "\(service.service)",
Expand All @@ -663,7 +663,7 @@ public actor ServiceGroup: Sendable, Service {
}
// The service that we were shutting down right now threw. Since it's failure
// behaviour is to shutdown the group we can continue
self.logger.debug(
self.logger?.debug(
"The service that we were shutting down threw. Continuing with the next one.",
metadata: [
self.loggingConfiguration.keys.serviceKey: "\(service.service)",
Expand All @@ -676,7 +676,7 @@ public actor ServiceGroup: Sendable, Service {
case .signalCaught(let signal):
if self.cancellationSignals.contains(signal) {
// We got signalled cancellation after graceful shutdown
self.logger.debug(
self.logger?.debug(
"Signal caught. Cancelling the group.",
metadata: [
self.loggingConfiguration.keys.signalKey: "\(signal)"
Expand All @@ -692,7 +692,7 @@ public actor ServiceGroup: Sendable, Service {
case .gracefulShutdownTimedOut:
// Gracefully shutting down took longer than the user configured
// so we have to escalate it now.
self.logger.debug(
self.logger?.debug(
"Graceful shutdown took longer than allowed by the configuration. Cancelling the group now.",
metadata: [
self.loggingConfiguration.keys.serviceKey: "\(service.service)"
Expand All @@ -706,7 +706,7 @@ public actor ServiceGroup: Sendable, Service {
case .cancellationCaught:
// We caught cancellation in our child task so we have to spawn
// our cancellation timeout task if needed
self.logger.debug("Caught cancellation.")
self.logger?.debug("Caught cancellation.")
self.cancelGroupAndSpawnTimeoutIfNeeded(
group: &group,
cancellationTimeoutTask: &cancellationTimeoutTask
Expand Down Expand Up @@ -741,7 +741,7 @@ public actor ServiceGroup: Sendable, Service {
) {
guard cancellationTimeoutTask == nil else {
// We already have a cancellation timeout task running.
self.logger.debug(
self.logger?.debug(
"Task cancellation timeout task already running."
)
return
Expand All @@ -756,7 +756,7 @@ public actor ServiceGroup: Sendable, Service {
// from being cancelled.
cancellationTimeoutTask = Task {
do {
self.logger.debug(
self.logger?.debug(
"Task cancellation timeout task started."
)
try await Task.sleep(
Expand All @@ -765,7 +765,7 @@ public actor ServiceGroup: Sendable, Service {
attosecondsComponent: maximumCancellationDuration.attosecondsComponent
)
)
self.logger.debug(
self.logger?.debug(
"Cancellation took longer than allowed by the configuration."
)
fatalError("Cancellation took longer than allowed by the configuration.")
Expand Down
Loading