Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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: 9 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ jobs:
# with_android: true
with_linting: true
secrets: inherit

package-traits:
runs-on: ubuntu-latest
container: swift:6.2-bookworm
steps:
- name: Check out ConsoleKit
uses: actions/checkout@v6
- name: Run tests with traits disabled
run: swift test --disable-default-traits

# integration-check:
# runs-on: ubuntu-latest
Expand Down
10 changes: 7 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@ let package = Package(
.library(name: "ConsoleKit", targets: ["ConsoleKit"]),
.library(name: "ConsoleLogger", targets: ["ConsoleLogger"]),
],
traits: [
.trait(name: "ConfigReader", description: "Create ConsoleLogger using Swift Configuration"),
.default(enabledTraits: ["ConfigReader"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-log.git", from: "1.8.0"),
.package(url: "https://github.com/apple/swift-async-algorithms.git", from: "1.1.1"),
.package(url: "https://github.com/apple/swift-configuration.git", from: "1.0.0"),
.package(url: "https://github.com/apple/swift-configuration.git", from: "1.0.0", traits: [.defaults, "CommandLineArguments"]),
],
targets: [
.target(
Expand All @@ -37,15 +41,15 @@ let package = Package(
name: "ConsoleLogger",
dependencies: [
.product(name: "Logging", package: "swift-log"),
.product(name: "Configuration", package: "swift-configuration"),
.product(name: "Configuration", package: "swift-configuration", condition: .when(traits: ["ConfigReader"])),
],
swiftSettings: swiftSettings
),
.testTarget(
name: "ConsoleLoggerTests",
dependencies: [
.target(name: "ConsoleLogger"),
.product(name: "Configuration", package: "swift-configuration"),
.product(name: "Configuration", package: "swift-configuration", condition: .when(traits: ["ConfigReader"])),
],
swiftSettings: swiftSettings
),
Expand Down
57 changes: 31 additions & 26 deletions Sources/ConsoleLogger/ConsoleLogger+bootstrap.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
public import Configuration
public import Logging

#if ConfigReader
public import Configuration
#endif

extension ConsoleLogger {
/// Bootstraps a ``ConsoleLogger`` to the `LoggingSystem`, so that logger will be used in `Logger.init(label:)`.
///
Expand Down Expand Up @@ -36,25 +39,26 @@ extension ConsoleLogger {
/// ```
///
/// - Parameters:
/// - print: The ``ConsoleLoggerPrinter`` used to output log messages.
/// - printer: The ``ConsoleLoggerPrinter`` used to output log messages.
/// - level: The minimum level of message that the logger will output. This defaults to `.info`.
/// - metadata: Extra metadata to log with all messages. This defaults to an empty dictionary.
/// - metadataProvider: The metadata provider to bootstrap the logging system with.
/// - fragment: The logger fragment which will be used to build the logged messages.
public static func bootstrap(
print: any ConsoleLoggerPrinter = DefaultConsoleLoggerPrinter(),
printer: any ConsoleLoggerPrinter = DefaultConsoleLoggerPrinter(),
level: Logger.Level = .info,
metadata: Logger.Metadata = [:],
metadataProvider: Logger.MetadataProvider? = nil,
@LoggerFragmentBuilder fragment: () -> T
) {
self.bootstrap(fragment: fragment(), level: level, metadata: metadata, metadataProvider: metadataProvider)
self.bootstrap(fragment: fragment(), printer: printer, level: level, metadata: metadata, metadataProvider: metadataProvider)
}

#if ConfigReader
/// Bootstraps a ``ConsoleLogger`` to the `LoggingSystem`, so that logger will be used in `Logger.init(label:)`.
///
/// ```swift
/// ConsoleLogger.bootstrap(config: ConfigReader(...))
/// ConsoleLogger.bootstrapWithConfigReader(config: ConfigReader(...))
/// ```
///
/// ## Configuration keys
Expand All @@ -63,54 +67,55 @@ extension ConsoleLogger {
/// - Parameters:
/// - fragment: The logger fragment which will be used to build the logged messages.
/// - printer: The ``ConsoleLoggerPrinter`` used to output log messages.
/// - config: The config reader to read the log level from. This defaults to `.info`.
/// - config: The config reader to read the log level from. A default `ConfigReader` is provided which reads from command line arguments and environment variables.
/// - metadata: Extra metadata to log with all messages. This defaults to an empty dictionary.
/// - metadataProvider: The metadata provider to bootstrap the logging system with.
public static func bootstrap(
public static func bootstrapWithConfigReader(
fragment: T = .default,
printer: any ConsoleLoggerPrinter = DefaultConsoleLoggerPrinter(),
config: ConfigReader,
config: ConfigReader = ConfigReader(providers: [CommandLineArgumentsProvider(), EnvironmentVariablesProvider()]),
metadata: Logger.Metadata = [:],
metadataProvider: Logger.MetadataProvider? = nil
) {
LoggingSystem.bootstrap(
{
ConsoleLogger(
fragment: fragment,
printer: printer,
label: $0,
level: config.string(forKey: "log.level", as: Logger.Level.self, default: .info),
metadata: metadata,
metadataProvider: $1
)
},
self.bootstrap(
fragment: fragment,
printer: printer,
level: config.string(forKey: "log.level", as: Logger.Level.self, default: .info),
metadata: metadata,
metadataProvider: metadataProvider
)
}

/// Bootstraps a ``ConsoleLogger`` to the `LoggingSystem`, so that logger will be used in `Logger.init(label:)`.
///
/// ```swift
/// ConsoleLogger.bootstrap(config: ConfigReader(...)) {
/// ConsoleLogger.bootstrapWithConfigReader(config: ConfigReader(...)) {
/// TimestampFragment()
/// }
/// ```
/// ## Configuration keys
/// - `log.level` (string, optional, default: `"info"`): The minimum level of message that the logger will output.
///
/// - Parameters:
/// - print: The ``ConsoleLoggerPrinter`` used to output log messages.
/// - config: The config reader to read the log level from. This defaults to `.info`.
/// - printer: The ``ConsoleLoggerPrinter`` used to output log messages.
/// - config: The config reader to read the log level from. A default `ConfigReader` is provided which reads from command line arguments and environment variables.
/// - metadata: Extra metadata to log with all messages. This defaults to an empty dictionary.
/// - metadataProvider: The metadata provider to bootstrap the logging system with.
/// - fragment: The logger fragment which will be used to build the logged messages.
public static func bootstrap(
print: any ConsoleLoggerPrinter = DefaultConsoleLoggerPrinter(),
config: ConfigReader,
public static func bootstrapWithConfigReader(
printer: any ConsoleLoggerPrinter = DefaultConsoleLoggerPrinter(),
config: ConfigReader = ConfigReader(providers: [CommandLineArgumentsProvider(), EnvironmentVariablesProvider()]),
metadata: Logger.Metadata = [:],
metadataProvider: Logger.MetadataProvider? = nil,
@LoggerFragmentBuilder fragment: () -> T
) {
self.bootstrap(fragment: fragment(), config: config, metadata: metadata, metadataProvider: metadataProvider)
self.bootstrapWithConfigReader(
fragment: fragment(),
printer: printer,
config: config,
metadata: metadata,
metadataProvider: metadataProvider
)
}
#endif
}
7 changes: 6 additions & 1 deletion Sources/ConsoleLogger/ConsoleLogger.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
public import Configuration
public import Logging

#if ConfigReader
public import Configuration
#endif

/// Outputs logs to console via a ``LoggerFragment`` pipeline.
public struct ConsoleLogger<T: LoggerFragment>: LogHandler, Sendable {
public let label: String
Expand Down Expand Up @@ -70,6 +73,7 @@ public struct ConsoleLogger<T: LoggerFragment>: LogHandler, Sendable {
self.metadataProvider = metadataProvider
}

#if ConfigReader
/// Creates a new ``ConsoleLogger`` instance.
///
/// ## Configuration keys
Expand Down Expand Up @@ -125,6 +129,7 @@ public struct ConsoleLogger<T: LoggerFragment>: LogHandler, Sendable {
self.logLevel = config.string(forKey: "log.level", as: Logger.Level.self, default: .debug)
self.metadataProvider = metadataProvider
}
#endif

/// See `LogHandler[metadataKey:]`.
///
Expand Down
7 changes: 6 additions & 1 deletion Tests/ConsoleLoggerTests/LoggingTests.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Configuration
import ConsoleLogger
import Logging
import Testing
Expand All @@ -17,6 +16,10 @@ import WASILibc
import CRT
#endif

#if ConfigReader
import Configuration
#endif

@Suite("ConsoleLogger Tests")
struct ConsoleLoggerTests {
@Test("Log Handler Check")
Expand Down Expand Up @@ -186,6 +189,7 @@ struct ConsoleLoggerTests {
)
}

#if ConfigReader
@Test("Log Level from ConfigReader", .serialized, arguments: Logger.Level.allCases)
func logLevelFromConfigReader(level: Logger.Level) {
let config = ConfigReader(provider: InMemoryProvider(values: ["log.level": .init(stringLiteral: level.rawValue)]))
Expand All @@ -201,6 +205,7 @@ struct ConsoleLoggerTests {
: "logged"
expect(printer: printer, logs: level, message: expectedMessage)
}
#endif
}

private func expect(
Expand Down