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..153b5443 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,30 +8,42 @@ on: jobs: unit-tests: + permissions: + 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 + enable_all_traits: true 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 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 @@ Documentation Team Chat MIT License -Continuous Integration -Code Coverage +Continuous Integration +Code Coverage Swift 6.1+

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/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 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 ) }