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
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Benchmark
import ConsoleKit
import ConsoleLogger
import Logging

Expand All @@ -26,10 +25,9 @@ let benchmarks: @Sendable () -> Void = {
"Logging",
configuration: .init(
setup: {
let console = TestConsole()
LoggingSystem.bootstrap(
{ label, provider in
ConsoleLogger(label: label, console: console)
ConsoleLogger(label: label)
},
metadataProvider: .init {
["provided1": "from metadata provider", "provided2": "another metadata provider"]
Expand All @@ -54,9 +52,7 @@ let benchmarks: @Sendable () -> Void = {
"LoggerFragmentBuilder",
configuration: .init(
setup: {
let console = TestConsole()
LoggingSystem.bootstrap(
console: console,
metadataProvider: .init {
["provided1": "from metadata provider", "provided2": "another metadata provider"]
}
Expand Down
47 changes: 0 additions & 47 deletions Benchmarks/ConsoleLoggerBenchmarks/TestConsole.swift

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"mallocCountTotal" : 52,
"peakMemoryResident" : 14278655
"mallocCountTotal" : 38,
"peakMemoryResident" : 11042816
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"mallocCountTotal" : 48,
"peakMemoryResident" : 13279231
"mallocCountTotal" : 30,
"peakMemoryResident" : 11108352
}
4 changes: 1 addition & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ let package = Package(
.target(
name: "ConsoleLogger",
dependencies: [
.product(name: "Logging", package: "swift-log"),
.target(name: "ConsoleKit"),
.product(name: "Logging", package: "swift-log")
],
swiftSettings: swiftSettings
),
Expand All @@ -50,7 +49,6 @@ let package = Package(
.executableTarget(
name: "ConsoleLoggerExample",
dependencies: [
.target(name: "ConsoleKit"),
.target(name: "ConsoleLogger"),
.product(name: "Logging", package: "swift-log"),
],
Expand Down
38 changes: 38 additions & 0 deletions Sources/ConsoleLogger/ANSIColor.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#if canImport(Darwin)
import Darwin.C
#elseif canImport(Glibc)
@preconcurrency import Glibc
#elseif canImport(Musl)
@preconcurrency import Musl
#elseif canImport(Android)
@preconcurrency import Android
#elseif os(WASI)
import WASILibc
#elseif os(Windows)
import CRT
#endif

enum ANSIColor: String {
case red = "\u{001B}[31m"
case green = "\u{001B}[32m"
case yellow = "\u{001B}[33m"
case cyan = "\u{001B}[36m"
case brightRed = "\u{001B}[91m"
}

extension String {
func colored(_ color: ANSIColor?) -> String {
guard supportsANSICommands, let color else { return self }
return color.rawValue + self + "\u{001B}[0m"
}
}

private var supportsANSICommands: Bool {
#if Xcode
// Xcode output does not support ANSI commands
return false
#else
// If STDOUT is not an interactive terminal then omit ANSI commands
return isatty(STDOUT_FILENO) > 0
#endif
}
37 changes: 18 additions & 19 deletions Sources/ConsoleLogger/ConsoleLogger.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
public import ConsoleKit
public import Logging

/// Outputs logs to a `Console` via a ``LoggerFragment`` pipeline.
/// Outputs logs to console via a ``LoggerFragment`` pipeline.
public struct ConsoleLogger<T: LoggerFragment>: LogHandler, Sendable {
public let label: String

Expand All @@ -14,65 +13,65 @@ public struct ConsoleLogger<T: LoggerFragment>: LogHandler, Sendable {
/// See `LogHandler.logLevel`.
public var logLevel: Logger.Level

/// The conosle that the messages will get logged to.
public let console: any Console

/// The ``LoggerFragment`` this logger outputs through.
public var fragment: T

/// The printer used to output log messages. Used for testing purposes only.
private let printer: any ConsoleLoggerPrinter

/// Creates a new ``ConsoleLogger`` instance.
///
/// - Parameters:
/// - fragment: The ``LoggerFragment`` this logger outputs through.
/// - printer: The ``ConsoleLoggerPrinter`` used to output log messages.
/// - label: Unique identifier for this logger.
/// - console: The console to log the messages to.
/// - 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`.
public init(
fragment: T = .default,
printer: any ConsoleLoggerPrinter = DefaultConsoleLoggerPrinter(),
label: String,
console: any Console,
level: Logger.Level = .debug,
metadata: Logger.Metadata = [:],
metadataProvider: Logger.MetadataProvider? = nil
) {
self.fragment = fragment
self.printer = printer
self.label = label
self.metadata = metadata
self.logLevel = level
self.console = console
self.metadataProvider = metadataProvider
}

/// Creates a new ``ConsoleLogger`` instance.
///
/// - Parameters:
/// - printer: The ``ConsoleLoggerPrinter`` used to output log messages.
/// - label: Unique identifier for this logger.
/// - console: The console to log the messages to.
/// - 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`.
/// - fragment: The ``LoggerFragment`` this logger outputs through.
public init(
printer: any ConsoleLoggerPrinter = DefaultConsoleLoggerPrinter(),
label: String,
console: any Console,
level: Logger.Level = .debug,
metadata: Logger.Metadata = [:],
metadataProvider: Logger.MetadataProvider? = nil,
@LoggerFragmentBuilder fragment: () -> T
) {
self.fragment = fragment()
self.printer = printer
self.label = label
self.metadata = metadata
self.logLevel = level
self.console = console
self.metadataProvider = metadataProvider
}

/// See `LogHandler[metadataKey:]`.
///
/// This just acts as a getter/setter for the `.metadata` property.
/// This just acts as a getter/setter for the ``ConsoleLogger/metadata`` property.
public subscript(metadataKey key: String) -> Logger.Metadata.Value? {
get { self.metadata[key] }
set { self.metadata[key] = newValue }
Expand Down Expand Up @@ -104,19 +103,19 @@ public struct ConsoleLogger<T: LoggerFragment>: LogHandler, Sendable {
)

self.fragment.write(&record, to: &output)
self.console.output(output.text)
self.printer.print(output.text)
}
}

extension Logger.Level {
/// Converts log level to console style
public var style: ConsoleStyle {
var style: ANSIColor? {
switch self {
case .trace, .debug: .plain
case .info, .notice: .info
case .warning: .warning
case .error: .error
case .critical: ConsoleStyle(color: .brightRed)
case .trace, .debug: nil
case .info, .notice: .cyan
case .warning: .yellow
case .error: .red
case .critical: .brightRed
}
}

Expand Down
20 changes: 20 additions & 0 deletions Sources/ConsoleLogger/ConsoleLoggerPrinter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/// Defines a printer used by a ``ConsoleLogger`` to output log messages.
public protocol ConsoleLoggerPrinter: Sendable {
/// The method called by a ``ConsoleLogger`` to print a log message.
///
/// - Parameter string: The string to print.
func print(_ string: String)
}

/// The default ``ConsoleLoggerPrinter`` that prints to standard output.
public struct DefaultConsoleLoggerPrinter: ConsoleLoggerPrinter {
/// Prints the given string to standard output using `Swift.print(_:)`.
///
/// - Parameter string: The string to print.
public func print(_ string: String) {
Swift.print(string)
}

/// Creates a new ``DefaultConsoleLoggerPrinter``.
public init() {}
}
9 changes: 3 additions & 6 deletions Sources/ConsoleLogger/Docs.docc/GettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,10 @@ Keep in mind that you can also create your own custom fragments by conforming to

### Bootstrapping the LoggingSystem

Build a ``ConsoleLogger`` with a custom or default fragment and a `ConsoleKit` `Console` (usually a `Terminal`), and register it with the `LoggingSystem`:
Build a ``ConsoleLogger`` with a custom or default fragment and register it with the `LoggingSystem`:

```swift
LoggingSystem.bootstrap(
fragment: .timestampDefault(),
console: Terminal()
)
LoggingSystem.bootstrap(fragment: .timestampDefault())

// Prints "2023-08-21T00:00:00Z [ INFO ] Logged!"
Logger(label: "EXAMPLE").info("Logged!")
Expand All @@ -89,7 +86,7 @@ You can also create multiple loggers with different labels and fragments as need

```swift
let logger = Logger(label: "codes.vapor.console") { label in
ConsoleLogger(label: label, console: console) {
ConsoleLogger(label: label) {
SpacedFragment {
"ConsoleLogger" // This is equivalent to LiteralFragment("ConsoleLogger")
LabelFragment()
Expand Down
9 changes: 7 additions & 2 deletions Sources/ConsoleLogger/Docs.docc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ A `SwiftLog` `LogHandler` implementation for customizable logging to a console.

- <doc:GettingStarted>
- ``ConsoleLogger``
- ``LogRecord``
- ``ConsoleLogger/Logging``

### Logger Fragments
Expand All @@ -42,4 +41,10 @@ A `SwiftLog` `LogHandler` implementation for customizable logging to a console.
- ``SystemTimestampSource``
- ``TimestampFragment``
- ``DefaultLoggerFragmentType``
- ``TimestampDefaultLoggerFragmentType``
- ``TimestampDefaultLoggerFragmentType``

### Miscellaneous

- ``LogRecord``
- ``ConsoleLoggerPrinter``
- ``DefaultConsoleLoggerPrinter``
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import ConsoleKit
import Logging

/// The type of the default ``LoggerFragment``.
Expand Down
Loading
Loading