Skip to content

Commit

Permalink
update comments and document
Browse files Browse the repository at this point in the history
  • Loading branch information
fatbobman committed Oct 28, 2024
1 parent fa4f060 commit e409510
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 7 deletions.
15 changes: 14 additions & 1 deletion Sources/SimpleLogger/Backend/ConsoleBackend.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,32 @@

import Foundation

/// 示例:控制台日志后端
/// An implementation of the `LoggerBackend` protocol that logs messages to the console.
public final class ConsoleLogBackend: LoggerBackend {
/// The subsystem name.
public let subsystem: String

/// Initializes a `ConsoleLogBackend` instance with the specified subsystem.
///
/// - Parameters:
/// - subsystem: The subsystem name.
public init(subsystem: String = "console logger") {
self.subsystem = subsystem
}

/// A date formatter for formatting the timestamp.
let dateFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
return dateFormatter
}()

/// Logs a message with the specified level, message, and metadata.
///
/// - Parameters:
/// - level: The log level.
/// - message: The message to log.
/// - metadata: The metadata to log.
public func log(level: LogLevel, message: String, metadata: [String: String]?) {
let timestamp = dateFormatter.string(from: Date())
let fullMessage = "\(timestamp) [\(level.rawValue.uppercased())] " +
Expand Down
10 changes: 9 additions & 1 deletion Sources/SimpleLogger/Backend/LoggerBackendProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,16 @@

import Foundation

/// 日志后端协议
/// A protocol that defines the interface for a logger backend.
public protocol LoggerBackend: Sendable {
/// The subsystem name.
var subsystem: String { get }

/// Logs a message with the specified level, message, and metadata.
///
/// - Parameters:
/// - level: The log level.
/// - message: The message to log.
/// - metadata: The metadata to log.
func log(level: LogLevel, message: String, metadata: [String: String]?)
}
16 changes: 14 additions & 2 deletions Sources/SimpleLogger/Backend/OSLogBackend.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@
import Foundation
import OSLog

/// OSLog 后端实现
/// An implementation of the `LoggerBackend` protocol that logs messages to OSLog.
public final class OSLogBackend: LoggerBackend {
public let subsystem: String
let logger: Logger

// 从环境变量中获取是否输出日志的选项
/// A boolean value that indicates whether the logger is enabled.
let loggerEnabled: Bool

/// Initializes an `OSLogBackend` instance with the specified subsystem and category.
///
/// - Parameters:
/// - subsystem: The subsystem name.
/// - category: The category name.
/// - environmentKey: The environment key to check for disabling the logger.
public init(subsystem: String, category: String, environmentKey: String = "DisableLogger") {
self.subsystem = subsystem
logger = Logger(subsystem: subsystem, category: category)
Expand All @@ -30,6 +36,12 @@ public final class OSLogBackend: LoggerBackend {
}
}

/// Logs a message with the specified level, message, and metadata.
///
/// - Parameters:
/// - level: The log level.
/// - message: The message to log.
/// - metadata: The metadata to log.
public func log(level: LogLevel, message: String, metadata: [String: String]?) {
let osLogType: OSLogType = {
switch level {
Expand Down
17 changes: 15 additions & 2 deletions Sources/SimpleLogger/LogLevel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,23 @@
// ------------------------------------------------
// Copyright © 2024-present Fatbobman. All rights reserved.

/// 日志级别枚举
/// An enumeration that defines the log levels.
public enum LogLevel: String, Comparable, Sendable {
case debug, info, warning, error
/// The debug log level.
case debug
/// The info log level.
case info
/// The warning log level.
case warning
/// The error log level.
case error

/// Compares two log levels.
///
/// - Parameters:
/// - lhs: The left log level.
/// - rhs: The right log level.
/// - Returns: A boolean value indicating whether the left log level is less than the right log level.
public static func < (lhs: LogLevel, rhs: LogLevel) -> Bool {
let order: [LogLevel] = [.debug, .info, .warning, .error]
return order.firstIndex(of: lhs)! < order.firstIndex(of: rhs)!
Expand Down
15 changes: 14 additions & 1 deletion Sources/SimpleLogger/LoggerManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@

import Foundation

/// 日志管理器
/// A logger manager that logs messages to a backend.
public final class LoggerManager: LoggerManagerProtocol, @unchecked Sendable {
let backend: LoggerBackend
let queue: DispatchQueue

/// Initializes a `LoggerManager` instance with the specified backend and dispatch queue quality of service.
///
/// - Parameters:
/// - backend: The logger backend.
/// - qos: The dispatch queue quality of service.
public init(
backend: LoggerBackend,
qos: DispatchQoS = .utility
Expand All @@ -24,6 +29,14 @@ public final class LoggerManager: LoggerManagerProtocol, @unchecked Sendable {
queue = DispatchQueue(label: backend.subsystem, qos: qos)
}

/// Logs a message with the specified level, file, function, and line.
///
/// - Parameters:
/// - message: The message to log.
/// - level: The log level.
/// - file: The file name.
/// - function: The function name.
/// - line: The line number.
public func log(
_ message: String,
level: LogLevel = .debug,
Expand Down
48 changes: 48 additions & 0 deletions Sources/SimpleLogger/LoggerManagerProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,16 @@

import Foundation

/// A protocol that defines the interface for a logger manager.
public protocol LoggerManagerProtocol: Sendable {
/// Logs a message with the specified level, file, function, and line.
///
/// - Parameters:
/// - message: The message to log.
/// - level: The log level.
/// - file: The file name.
/// - function: The function name.
/// - line: The line number.
func log(
_ message: String,
level: LogLevel,
Expand All @@ -21,29 +30,68 @@ public protocol LoggerManagerProtocol: Sendable {
)
}

/// Default implementations for the `LoggerManagerProtocol`.
extension LoggerManagerProtocol {
/// Logs a debug message.
///
/// - Parameters:
/// - message: The message to log.
/// - file: The file name.
/// - function: The function name.
/// - line: The line number.
public func debug(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
log(message, level: .debug, file: file, function: function, line: line)
}

/// Logs an info message.
///
/// - Parameters:
/// - message: The message to log.
/// - file: The file name.
/// - function: The function name.
/// - line: The line number.
public func info(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
log(message, level: .info, file: file, function: function, line: line)
}

/// Logs a warning message.
///
/// - Parameters:
/// - message: The message to log.
/// - file: The file name.
/// - function: The function name.
/// - line: The line number.
public func warning(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
log(message, level: .warning, file: file, function: function, line: line)
}

/// Logs an error message.
///
/// - Parameters:
/// - message: The message to log.
/// - file: The file name.
/// - function: The function name.
/// - line: The line number.
public func error(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
log(message, level: .error, file: file, function: function, line: line)
}
}

/// Default implementations for the `LoggerManagerProtocol`.
extension LoggerManagerProtocol where Self == LoggerManager {
/// Creates a default `LoggerManager` instance with the specified subsystem and category.
///
/// - Parameters:
/// - subsystem: The subsystem name.
/// - category: The category name.
static func `default`(subsystem: String, category: String) -> Self {
LoggerManager(backend: OSLogBackend(subsystem: subsystem, category: category))
}

/// Creates a `LoggerManager` instance that logs to the console.
///
/// - Parameters:
/// - subsystem: The subsystem name.
static func console(subsystem: String = "Console Logger") -> Self {
LoggerManager(backend: ConsoleLogBackend(subsystem: subsystem))
}
Expand Down
107 changes: 107 additions & 0 deletions Sources/SimpleLogger/SimpleLogger.docc/SimpleLogger.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# ``SimpleLogger``

A simple logging library for Swift 6, providing easy-to-use logging functionalities with support for different log levels and backends.

## Features

- **Log Levels**: Supports `.debug`, `.info`, `.warning`, and `.error` levels.
- **Custom Backends**: Easily create custom log backends by conforming to `LoggerBackend`.
- **Built-in Backends**: Includes `ConsoleLogBackend` and `OSLogBackend`.
- **Thread Safety**: Utilizes `DispatchQueue` for thread-safe logging.
- **Environment Configurable**: Control logging output via environment variables.

## Usage

### Creating a Logger

#### Default OS Logger

```swift
let logger: LoggerManagerProtocol = .default(subsystem: "com.yourapp", category: "networking")
```

#### Console Logger

```swift
let logger: LoggerManagerProtocol = .console()
```

### Logging Messages

```swift
logger.debug("This is a debug message")
logger.info("This is an info message")
logger.warning("This is a warning message")
logger.error("This is an error message")
```

### Custom Logger Backend

Conform to `LoggerBackend` to create a custom backend:

```swift
public protocol LoggerBackend: Sendable {
var subsystem: String { get }
func log(level: LogLevel, message: String, metadata: [String: String]?)
}
```

Example:

```swift
struct CustomLoggerBackend: LoggerBackend {
let subsystem: String = "Custom Logger"

func log(level: LogLevel, message: String, metadata: [String: String]?) {
// Custom logging implementation
}
}
```

### Disabling Logs

Set the `DisableLogger` environment variable to disable logging:

```swift
ProcessInfo.processInfo.environment["DisableLogger"] = "true"
```

## Examples

### Using the Default Logger

```swift
import SimpleLogger

let logger: LoggerManagerProtocol = .default(subsystem: "com.example.app", category: "general")
logger.info("App started")
```

### Using the Console Logger

```swift
import SimpleLogger

let logger: LoggerManagerProtocol = .console()
logger.debug("Debugging information")
```

### Custom Logger Test

```swift
struct CustomLogger: LoggerManagerProtocol {
let expect: @Sendable (String, LogLevel) -> Void

func log(_ message: String, level: LogLevel, file: String, function: String, line: Int) {
expect(message, level)
}
}

let logger: LoggerManagerProtocol = CustomLogger(expect: { msg, level in
#expect(msg == "Hello, World!")
#expect(level == .info)
})
logger.info("Hello, World!")
```


0 comments on commit e409510

Please sign in to comment.