From abfa4ff5100656824658a14f768cdd24d512ed72 Mon Sep 17 00:00:00 2001
From: Gwynne Raskind
Date: Wed, 1 Apr 2026 08:40:39 -0500
Subject: [PATCH 1/4] Cherry-pick the update for swift-log 1.11.0 from main
---
.github/dependabot.yml | 18 ++++++
.github/workflows/test.yml | 21 +++++--
Package.swift | 2 +-
README.md | 4 +-
.../images/vapor-consolekit-logo.svg | 30 ++++++----
.../ConsoleKit/Docs.docc/theme-settings.json | 10 ++--
Sources/ConsoleKit/Terminal/ANSI.swift | 4 ++
Sources/ConsoleKit/Terminal/Terminal.swift | 5 +-
Sources/ConsoleLogger/ANSIColor.swift | 2 +
.../ConsoleLogger+bootstrap.swift | 8 +--
Sources/ConsoleLogger/ConsoleLogger.swift | 59 ++++++++-----------
.../images/vapor-consolekit-logo.svg | 30 ++++++----
.../Docs.docc/theme-settings.json | 10 ++--
.../LoggerFragments/LoggerFragment.swift | 2 +-
Tests/ConsoleLoggerTests/LoggingTests.swift | 6 +-
15 files changed, 119 insertions(+), 92 deletions(-)
create mode 100644 .github/dependabot.yml
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..9f8d71ff
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,18 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ groups:
+ dependencies:
+ patterns:
+ - "*"
+ - package-ecosystem: "swift"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ groups:
+ dependencies:
+ patterns:
+ - "*"
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 3de54ad2..1aefbcbf 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -8,6 +8,8 @@ on:
jobs:
unit-tests:
+ permissions:
+ contents: read
uses: vapor/ci/.github/workflows/run-unit-tests.yml@main
with:
# with_windows: true
@@ -17,21 +19,30 @@ jobs:
secrets: inherit
package-traits:
+ permissions:
+ contents: read
runs-on: ubuntu-latest
- container: swift:6.2-bookworm
+ container: swift:noble
steps:
- name: Check out ConsoleKit
uses: actions/checkout@v6
- name: Run tests with traits disabled
run: swift test --disable-default-traits
-
+
+ submit-dependencies:
+ permissions:
+ contents: write
+ if: ${{ github.event_name == 'push' }}
+ uses: vapor/ci/.github/workflows/submit-deps.yml@main
+ secrets: inherit
+
# integration-check:
# runs-on: ubuntu-latest
# container: swift:noble
# steps:
- # - uses: actions/checkout@v4
+ # - uses: actions/checkout@v6
# with: { path: console-kit }
- # - uses: actions/checkout@v4
+ # - uses: actions/checkout@v6
# with: { repository: 'vapor/vapor', path: vapor }
# - run: swift package --package-path vapor edit console-kit --path console-kit
- # - run: SWIFT_DETERMINISTIC_HASHING=1 swift test --package-path vapor
\ No newline at end of file
+ # - run: swift test --package-path vapor
\ No newline at end of file
diff --git a/Package.swift b/Package.swift
index e2fa3cd2..e842be65 100644
--- a/Package.swift
+++ b/Package.swift
@@ -18,7 +18,7 @@ let package = Package(
.default(enabledTraits: ["ConfigReader"]),
],
dependencies: [
- .package(url: "https://github.com/apple/swift-log.git", from: "1.8.0"),
+ .package(url: "https://github.com/apple/swift-log.git", from: "1.11.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", traits: [.defaults, "CommandLineArguments"]),
],
diff --git a/README.md b/README.md
index 9360f652..2daa5cdc 100644
--- a/README.md
+++ b/README.md
@@ -5,8 +5,8 @@
-
-
+
+
diff --git a/Sources/ConsoleKit/Docs.docc/images/vapor-consolekit-logo.svg b/Sources/ConsoleKit/Docs.docc/images/vapor-consolekit-logo.svg
index f3b1e796..0135210e 100644
--- a/Sources/ConsoleKit/Docs.docc/images/vapor-consolekit-logo.svg
+++ b/Sources/ConsoleKit/Docs.docc/images/vapor-consolekit-logo.svg
@@ -1,21 +1,25 @@
diff --git a/Sources/ConsoleKit/Docs.docc/theme-settings.json b/Sources/ConsoleKit/Docs.docc/theme-settings.json
index 2be67888..d7b909a4 100644
--- a/Sources/ConsoleKit/Docs.docc/theme-settings.json
+++ b/Sources/ConsoleKit/Docs.docc/theme-settings.json
@@ -1,21 +1,21 @@
{
"theme": {
- "aside": { "border-radius": "16px", "border-style": "double", "border-width": "3px" },
+ "aside": { "border-radius": "16px", "border-width": "3px", "border-style": "double" },
"border-radius": "0",
"button": { "border-radius": "16px", "border-width": "1px", "border-style": "solid" },
"code": { "border-radius": "16px", "border-width": "1px", "border-style": "solid" },
"color": {
"consolekit": "#392048",
- "documentation-intro-fill": "radial-gradient(circle at top, var(--color-consolekit) 30%, #000 100%)",
+ "documentation-intro-fill": "radial-gradient(circle at top, var(--color-consolekit) 30%, #000 100%)",
"documentation-intro-accent": "var(--color-consolekit)",
- "documentation-intro-eyebrow": "white",
+ "hero-eyebrow": "white",
"documentation-intro-figure": "white",
- "documentation-intro-title": "white",
+ "hero-title": "white",
"logo-base": { "dark": "#fff", "light": "#000" },
"logo-shape": { "dark": "#000", "light": "#fff" },
"fill": { "dark": "#000", "light": "#fff" }
},
- "icons": { "technology": "/consolekit/images/vapor-consolekit-logo.svg" }
+ "icons": { "technology": "/consolekit/images/ConsoleKit/vapor-consolekit-logo.svg" }
},
"features": {
"quickNavigation": { "enable": true },
diff --git a/Sources/ConsoleKit/Terminal/ANSI.swift b/Sources/ConsoleKit/Terminal/ANSI.swift
index 3151ba38..44f38b5a 100644
--- a/Sources/ConsoleKit/Terminal/ANSI.swift
+++ b/Sources/ConsoleKit/Terminal/ANSI.swift
@@ -60,7 +60,11 @@ extension Terminal {
// fdopen() on stdout is fast; also the returned file MUST NOT be fclose()d
// This avoids concurrency complaints due to accessing global `stdout`.
+ #if os(Windows)
+ fflush(_fdopen(_fileno(stdout), "w+"))
+ #else
fflush(fdopen(STDOUT_FILENO, "w+"))
+ #endif
}
}
diff --git a/Sources/ConsoleKit/Terminal/Terminal.swift b/Sources/ConsoleKit/Terminal/Terminal.swift
index 048f7936..0845d465 100644
--- a/Sources/ConsoleKit/Terminal/Terminal.swift
+++ b/Sources/ConsoleKit/Terminal/Terminal.swift
@@ -12,14 +12,11 @@ import Darwin.C
import WASILibc
#elseif os(Windows)
import CRT
+import WinSDK
#endif
import Synchronization
-#if os(Windows)
-import WinSDK
-#endif
-
/// Generic console that uses a mixture of Swift and C standard
/// libraries to fulfill protocol requirements.
public final class Terminal: Console, Sendable {
diff --git a/Sources/ConsoleLogger/ANSIColor.swift b/Sources/ConsoleLogger/ANSIColor.swift
index 854a3d9d..34eaf011 100644
--- a/Sources/ConsoleLogger/ANSIColor.swift
+++ b/Sources/ConsoleLogger/ANSIColor.swift
@@ -31,6 +31,8 @@ private var supportsANSICommands: Bool {
#if Xcode
// Xcode output does not support ANSI commands
return false
+ #elseif os(Windows)
+ return _isatty(_fileno(stdout)) > 0
#else
// If STDOUT is not an interactive terminal then omit ANSI commands
return isatty(STDOUT_FILENO) > 0
diff --git a/Sources/ConsoleLogger/ConsoleLogger+bootstrap.swift b/Sources/ConsoleLogger/ConsoleLogger+bootstrap.swift
index 537d63f9..45f7bb3b 100644
--- a/Sources/ConsoleLogger/ConsoleLogger+bootstrap.swift
+++ b/Sources/ConsoleLogger/ConsoleLogger+bootstrap.swift
@@ -5,7 +5,7 @@ public import Configuration
#endif
extension ConsoleLogger {
- /// Bootstraps a ``ConsoleLogger`` to the `LoggingSystem`, so that logger will be used in `Logger.init(label:)`.
+ /// Bootstraps a ``ConsoleLogger`` to the `LoggingSystem` as the default log handler.
///
/// ```swift
/// ConsoleLogger.bootstrap()
@@ -30,7 +30,7 @@ extension ConsoleLogger {
)
}
- /// Bootstraps a ``ConsoleLogger`` to the `LoggingSystem`, so that logger will be used in `Logger.init(label:)`.
+ /// Bootstraps a ``ConsoleLogger`` to the `LoggingSystem` as the default log handler.
///
/// ```swift
/// ConsoleLogger.bootstrap() {
@@ -55,7 +55,7 @@ extension ConsoleLogger {
}
#if ConfigReader
- /// Bootstraps a ``ConsoleLogger`` to the `LoggingSystem`, so that logger will be used in `Logger.init(label:)`.
+ /// Bootstraps a ``ConsoleLogger`` to the `LoggingSystem` as the default log handler.
///
/// ```swift
/// ConsoleLogger.bootstrapWithConfigReader(config: ConfigReader(...))
@@ -86,7 +86,7 @@ extension ConsoleLogger {
)
}
- /// Bootstraps a ``ConsoleLogger`` to the `LoggingSystem`, so that logger will be used in `Logger.init(label:)`.
+ /// Bootstraps a ``ConsoleLogger`` to the `LoggingSystem` as the default log handler.
///
/// ```swift
/// ConsoleLogger.bootstrapWithConfigReader(config: ConfigReader(...)) {
diff --git a/Sources/ConsoleLogger/ConsoleLogger.swift b/Sources/ConsoleLogger/ConsoleLogger.swift
index f6250d6c..e852ef69 100644
--- a/Sources/ConsoleLogger/ConsoleLogger.swift
+++ b/Sources/ConsoleLogger/ConsoleLogger.swift
@@ -6,15 +6,16 @@ public import Configuration
/// Outputs logs to console via a ``LoggerFragment`` pipeline.
public struct ConsoleLogger: LogHandler, Sendable {
+ /// The log handler's label.
public let label: String
- /// See `LogHandler.metadata`.
+ // See `LogHandler.metadata`.
public var metadata: Logger.Metadata
- /// See `LogHandler.metadataProvider`.
+ // See `LogHandler.metadataProvider`.
public var metadataProvider: Logger.MetadataProvider?
- /// See `LogHandler.logLevel`.
+ // See `LogHandler.logLevel`.
public var logLevel: Logger.Level
/// The ``LoggerFragment`` this logger outputs through.
@@ -29,9 +30,9 @@ public struct ConsoleLogger: LogHandler, Sendable {
/// - fragment: The ``LoggerFragment`` this logger outputs through.
/// - printer: The ``ConsoleLoggerPrinter`` used to output log messages.
/// - label: Unique identifier for this logger.
- /// - level: The minimum level of message that the logger will output. This defaults to `.debug`, the lowest level.
- /// - metadata: Extra metadata to log with the message. This defaults to an empty dictionary.
- /// - metadataProvider: The metadata provider to use for this logger. This defaults to `nil`.
+ /// - level: The minimum level of message that the logger will output. Defaults to `.debug`.
+ /// - metadata: Extra metadata to log with the message. Defaults to an empty dictionary.
+ /// - metadataProvider: The metadata provider to use for this logger. Defaults to `nil`.
public init(
fragment: T = .default,
printer: any ConsoleLoggerPrinter = DefaultConsoleLoggerPrinter(),
@@ -53,9 +54,9 @@ public struct ConsoleLogger: LogHandler, Sendable {
/// - Parameters:
/// - printer: The ``ConsoleLoggerPrinter`` used to output log messages.
/// - label: Unique identifier for this logger.
- /// - level: The minimum level of message that the logger will output. This defaults to `.debug`, the lowest level.
- /// - metadata: Extra metadata to log with the message. This defaults to an empty dictionary.
- /// - metadataProvider: The metadata provider to use for this logger. This defaults to `nil`.
+ /// - level: The minimum level of message that the logger will output. Defaults to `.debug`.
+ /// - metadata: Extra metadata to log with the message. Defaults to an empty dictionary.
+ /// - metadataProvider: The metadata provider to use for this logger. Defaults to `nil`.
/// - fragment: The ``LoggerFragment`` this logger outputs through.
public init(
printer: any ConsoleLoggerPrinter = DefaultConsoleLoggerPrinter(),
@@ -83,9 +84,9 @@ public struct ConsoleLogger: LogHandler, Sendable {
/// - fragment: The ``LoggerFragment`` this logger outputs through.
/// - printer: The ``ConsoleLoggerPrinter`` used to output log messages.
/// - label: Unique identifier for this logger.
- /// - config: The config reader to read the log level from. This defaults to `.debug`, the lowest level.
- /// - metadata: Extra metadata to log with the message. This defaults to an empty dictionary.
- /// - metadataProvider: The metadata provider to use for this logger. This defaults to `nil`.
+ /// - config: The config reader to read the log level from. Defaults to `.debug`.
+ /// - metadata: Extra metadata to log with the message. Defaults to an empty dictionary.
+ /// - metadataProvider: The metadata provider to use for this logger. Defaults to `nil`.
public init(
fragment: T = .default,
printer: any ConsoleLoggerPrinter = DefaultConsoleLoggerPrinter(),
@@ -131,33 +132,23 @@ public struct ConsoleLogger: LogHandler, Sendable {
}
#endif
- /// See `LogHandler[metadataKey:]`.
- ///
- /// This just acts as a getter/setter for the ``ConsoleLogger/metadata`` property.
+ // See `LogHandler.subscript(metadataKey:)`.
public subscript(metadataKey key: String) -> Logger.Metadata.Value? {
get { self.metadata[key] }
set { self.metadata[key] = newValue }
}
- /// See `LogHandler.log(level:message:metadata:source:file:function:line:)`.
- public func log(
- level: Logger.Level,
- message: Logger.Message,
- metadata: Logger.Metadata?,
- source: String,
- file: String,
- function: String,
- line: UInt
- ) {
+ // See `LogHandler.log(event:)`.
+ public func log(event: LogEvent) {
var output = FragmentOutput()
var record = LogRecord(
- level: level,
- message: message,
- metadata: metadata,
- source: source,
- file: file,
- function: function,
- line: line,
+ level: event.level,
+ message: event.message,
+ metadata: event.metadata,
+ source: event.source,
+ file: event.file,
+ function: event.function,
+ line: event.line,
label: self.label,
loggerLevel: self.logLevel,
loggerMetadata: self.metadata,
@@ -180,8 +171,4 @@ extension Logger.Level {
case .critical: .brightRed
}
}
-
- public var name: String {
- "\(self)".uppercased()
- }
}
diff --git a/Sources/ConsoleLogger/Docs.docc/images/vapor-consolekit-logo.svg b/Sources/ConsoleLogger/Docs.docc/images/vapor-consolekit-logo.svg
index f3b1e796..0135210e 100644
--- a/Sources/ConsoleLogger/Docs.docc/images/vapor-consolekit-logo.svg
+++ b/Sources/ConsoleLogger/Docs.docc/images/vapor-consolekit-logo.svg
@@ -1,21 +1,25 @@
diff --git a/Sources/ConsoleLogger/Docs.docc/theme-settings.json b/Sources/ConsoleLogger/Docs.docc/theme-settings.json
index 2be67888..73dd7e97 100644
--- a/Sources/ConsoleLogger/Docs.docc/theme-settings.json
+++ b/Sources/ConsoleLogger/Docs.docc/theme-settings.json
@@ -1,21 +1,21 @@
{
"theme": {
- "aside": { "border-radius": "16px", "border-style": "double", "border-width": "3px" },
+ "aside": { "border-radius": "16px", "border-width": "3px", "border-style": "double" },
"border-radius": "0",
"button": { "border-radius": "16px", "border-width": "1px", "border-style": "solid" },
"code": { "border-radius": "16px", "border-width": "1px", "border-style": "solid" },
"color": {
"consolekit": "#392048",
- "documentation-intro-fill": "radial-gradient(circle at top, var(--color-consolekit) 30%, #000 100%)",
+ "documentation-intro-fill": "radial-gradient(circle at top, var(--color-consolekit) 30%, #000 100%)",
"documentation-intro-accent": "var(--color-consolekit)",
- "documentation-intro-eyebrow": "white",
+ "hero-eyebrow": "white",
"documentation-intro-figure": "white",
- "documentation-intro-title": "white",
+ "hero-title": "white",
"logo-base": { "dark": "#fff", "light": "#000" },
"logo-shape": { "dark": "#000", "light": "#fff" },
"fill": { "dark": "#000", "light": "#fff" }
},
- "icons": { "technology": "/consolekit/images/vapor-consolekit-logo.svg" }
+ "icons": { "technology": "/consolekit/images/ConsoleLoger/vapor-consolekit-logo.svg" }
},
"features": {
"quickNavigation": { "enable": true },
diff --git a/Sources/ConsoleLogger/LoggerFragments/LoggerFragment.swift b/Sources/ConsoleLogger/LoggerFragments/LoggerFragment.swift
index 8d7c28db..45fb6336 100644
--- a/Sources/ConsoleLogger/LoggerFragments/LoggerFragment.swift
+++ b/Sources/ConsoleLogger/LoggerFragments/LoggerFragment.swift
@@ -196,7 +196,7 @@ public struct LevelFragment: LoggerFragment {
public init() {}
public func write(_ record: inout LogRecord, to output: inout FragmentOutput) {
- output += "[ \(record.level.name) ]".colored(record.level.style)
+ output += "[ \(record.level.rawValue.uppercased()) ]".colored(record.level.style)
output.needsSeparator = true
}
}
diff --git a/Tests/ConsoleLoggerTests/LoggingTests.swift b/Tests/ConsoleLoggerTests/LoggingTests.swift
index 9f79a0fb..65f0bd3f 100644
--- a/Tests/ConsoleLoggerTests/LoggingTests.swift
+++ b/Tests/ConsoleLoggerTests/LoggingTests.swift
@@ -167,7 +167,7 @@ struct ConsoleLoggerTests {
// Remove the timezone, since there doesn't appear to be a good way to mock it with strftime.
while logged.removeFirst() != " " {}
- #expect(logged == "[ \(Logger.Level.info.name) ] logged (ConsoleLoggerTests/LoggingTests.swift:1)")
+ #expect(logged == "[ \(Logger.Level.info.rawValue.uppercased()) ] logged (ConsoleLoggerTests/LoggingTests.swift:1)")
}
@Test("Source Fragment")
@@ -185,7 +185,7 @@ struct ConsoleLoggerTests {
#expect(
printer.testOutputQueue.first
- == "ConsoleLoggerTests [ \(Logger.Level.info.name) ] logged (ConsoleLoggerTests/LoggingTests.swift:1)"
+ == "ConsoleLoggerTests [ \(Logger.Level.info.rawValue.uppercased()) ] logged (ConsoleLoggerTests/LoggingTests.swift:1)"
)
}
@@ -217,7 +217,7 @@ private func expect(
) {
#expect(
printer.testOutputQueue.first ?? ""
- == "\(level == .trace ? "[ \(label) ] " : "")[ \(level.name) ] \(message)",
+ == "\(level == .trace ? "[ \(label) ] " : "")[ \(level.rawValue.uppercased()) ] \(message)",
sourceLocation: sourceLocation
)
}
From 762db16b92dfbbfad664a35846e0f9458d66f9fa Mon Sep 17 00:00:00 2001
From: Gwynne Raskind
Date: Wed, 1 Apr 2026 09:35:16 -0500
Subject: [PATCH 2/4] Add Windows and Android CI
---
.github/workflows/test.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 1aefbcbf..c7d004fd 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -12,9 +12,9 @@ jobs:
contents: read
uses: vapor/ci/.github/workflows/run-unit-tests.yml@main
with:
- # with_windows: true
+ with_windows: true
with_musl: true
- # with_android: true
+ with_android: true
with_linting: true
secrets: inherit
@@ -45,4 +45,4 @@ jobs:
# - uses: actions/checkout@v6
# with: { repository: 'vapor/vapor', path: vapor }
# - run: swift package --package-path vapor edit console-kit --path console-kit
- # - run: swift test --package-path vapor
\ No newline at end of file
+ # - run: swift test --package-path vapor
From 0e864adde0c6bfcaab43d724c53b003562f4971b Mon Sep 17 00:00:00 2001
From: Gwynne Raskind
Date: Wed, 1 Apr 2026 09:48:24 -0500
Subject: [PATCH 3/4] Windows fix
---
Sources/ConsoleKit/Terminal/Console.swift | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Sources/ConsoleKit/Terminal/Console.swift b/Sources/ConsoleKit/Terminal/Console.swift
index 2cf22136..1f85d21e 100644
--- a/Sources/ConsoleKit/Terminal/Console.swift
+++ b/Sources/ConsoleKit/Terminal/Console.swift
@@ -110,6 +110,8 @@ extension Console {
#if Xcode
// Xcode output does not support ANSI commands
return false
+ #elseif os(Windows)
+ return _isatty(_fileno(stdout)) > 0
#else
// If STDOUT is not an interactive terminal then omit ANSI commands
return isatty(STDOUT_FILENO) > 0
From 26f8b95cb909ffe975b46f2165a40ed898aeca77 Mon Sep 17 00:00:00 2001
From: Gwynne Raskind
Date: Wed, 1 Apr 2026 09:49:28 -0500
Subject: [PATCH 4/4] Update CI
---
.github/workflows/test.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index c7d004fd..153b5443 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -16,6 +16,7 @@ jobs:
with_musl: true
with_android: true
with_linting: true
+ enable_all_traits: true
secrets: inherit
package-traits: