From d1028b81c64ea1aa73d6b99f7b6476556056e61a Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Tue, 17 Oct 2023 09:43:24 +0300 Subject: [PATCH 1/7] Generate project structure --- Sources/Log/Classes/Log.swift | 6 ++++++ Tests/LogTests/LogTests.swift | 8 ++++++++ 2 files changed, 14 insertions(+) create mode 100644 Sources/Log/Classes/Log.swift create mode 100644 Tests/LogTests/LogTests.swift diff --git a/Sources/Log/Classes/Log.swift b/Sources/Log/Classes/Log.swift new file mode 100644 index 0000000..771861f --- /dev/null +++ b/Sources/Log/Classes/Log.swift @@ -0,0 +1,6 @@ +// +// Log +// Copyright © 2023 Space Code. All rights reserved. +// + +final class Log {} diff --git a/Tests/LogTests/LogTests.swift b/Tests/LogTests/LogTests.swift new file mode 100644 index 0000000..285a13b --- /dev/null +++ b/Tests/LogTests/LogTests.swift @@ -0,0 +1,8 @@ +// +// Log +// Copyright © 2023 Space Code. All rights reserved. +// + +import XCTest + +final class LogTests: XCTestCase {} From 327132fe6c13c29fb388768de784fecfd49b47ef Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Wed, 18 Oct 2023 17:37:43 +0300 Subject: [PATCH 2/7] Implement `log` package --- Sources/Log/Classes/Log.swift | 6 ------ Tests/LogTests/LogTests.swift | 8 -------- 2 files changed, 14 deletions(-) delete mode 100644 Sources/Log/Classes/Log.swift delete mode 100644 Tests/LogTests/LogTests.swift diff --git a/Sources/Log/Classes/Log.swift b/Sources/Log/Classes/Log.swift deleted file mode 100644 index 771861f..0000000 --- a/Sources/Log/Classes/Log.swift +++ /dev/null @@ -1,6 +0,0 @@ -// -// Log -// Copyright © 2023 Space Code. All rights reserved. -// - -final class Log {} diff --git a/Tests/LogTests/LogTests.swift b/Tests/LogTests/LogTests.swift deleted file mode 100644 index 285a13b..0000000 --- a/Tests/LogTests/LogTests.swift +++ /dev/null @@ -1,8 +0,0 @@ -// -// Log -// Copyright © 2023 Space Code. All rights reserved. -// - -import XCTest - -final class LogTests: XCTestCase {} From 87fa168ce7f211eeca629a6058db44c33d9aa5c5 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Thu, 18 Jan 2024 20:01:36 +0100 Subject: [PATCH 3/7] Update GitHub Actions workflow (#3) * Update `ci.yml` * Update the Ruby version from `2.7` to `3.1.4` * Update `CHANGELOG.md` * Add support for Swift 5.8 * Fix a typo --- .github/workflows/ci.yml | 188 ++++++++++++++++--- .github/workflows/danger.yml | 2 +- CHANGELOG.md | 5 + Package@swift-5.8.swift | 24 +++ Sources/Log/Classes/Core/Logger/Logger.swift | 2 +- 5 files changed, 191 insertions(+), 30 deletions(-) create mode 100644 Package@swift-5.8.swift diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d544d32..28d58cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,10 +13,6 @@ on: - "Source/**" - "Tests/**" -concurrency: - group: ci - cancel-in-progress: true - jobs: SwiftLint: runs-on: ubuntu-latest @@ -28,40 +24,176 @@ jobs: args: --strict env: DIFF_BASE: ${{ github.base_ref }} - Latest: - name: Test Latest (iOS, macOS, tvOS, watchOS) - runs-on: macOS-12 + macOS: + name: ${{ matrix.name }} + runs-on: ${{ matrix.runsOn }} + env: + DEVELOPER_DIR: "/Applications/${{ matrix.xcode }}.app/Contents/Developer" + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + include: + - xcode: "Xcode_15.0" + runsOn: macos-13 + name: "macOS 13, Xcode 15.0, Swift 5.9.0" + - xcode: "Xcode_14.3.1" + runsOn: macos-13 + name: "macOS 13, Xcode 14.3.1, Swift 5.8.0" + steps: + - uses: actions/checkout@v3 + - name: ${{ matrix.name }} + run: xcodebuild test -scheme "Log" -destination "platform=macOS" clean -enableCodeCoverage YES -resultBundlePath "test_output/${{ matrix.name }}.xcresult" || exit 1 + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3.1.0 + with: + token: ${{ secrets.CODECOV_TOKEN }} + xcode: true + xcode_archive_path: test_output/${{ matrix.name }}.xcresult + - uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.name }} + path: test_output + + iOS: + name: ${{ matrix.name }} + runs-on: ${{ matrix.runsOn }} + env: + DEVELOPER_DIR: "/Applications/${{ matrix.xcode }}.app/Contents/Developer" + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + include: + - destination: "OS=17.0.1,name=iPhone 14 Pro" + name: "iOS 17.0.1" + xcode: "Xcode_15.0" + runsOn: macos-13 + - destination: "OS=16.4,name=iPhone 14 Pro" + name: "iOS 16.4" + xcode: "Xcode_14.3.1" + runsOn: macos-13 + steps: + - uses: actions/checkout@v3 + - name: ${{ matrix.name }} + run: xcodebuild test -scheme "Log" -destination "${{ matrix.destination }}" clean -enableCodeCoverage YES -resultBundlePath "test_output/${{ matrix.name }}.xcresult" || exit 1 + - uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.name }} + path: test_output + + tvOS: + name: ${{ matrix.name }} + runs-on: ${{ matrix.runsOn }} + env: + DEVELOPER_DIR: "/Applications/${{ matrix.xcode }}.app/Contents/Developer" + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + include: + - destination: "OS=17.0,name=Apple TV" + name: "tvOS 17.0" + xcode: "Xcode_15.0" + runsOn: macos-13 + - destination: "OS=16.4,name=Apple TV" + name: "tvOS 16.4" + xcode: "Xcode_14.3.1" + runsOn: macos-13 + steps: + - uses: actions/checkout@v3 + - name: ${{ matrix.name }} + run: xcodebuild test -scheme "Log" -destination "${{ matrix.destination }}" clean -enableCodeCoverage YES -resultBundlePath "test_output/${{ matrix.name }}.xcresult" || exit 1 + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3.1.0 + with: + token: ${{ secrets.CODECOV_TOKEN }} + xcode: true + xcode_archive_path: test_output/${{ matrix.name }}.xcresult + - uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.name }} + path: test_output + + watchOS: + name: ${{ matrix.name }} + runs-on: ${{ matrix.runsOn }} env: - DEVELOPER_DIR: "/Applications/Xcode_14.1.app/Contents/Developer" - timeout-minutes: 10 + DEVELOPER_DIR: "/Applications/${{ matrix.xcode }}.app/Contents/Developer" + timeout-minutes: 20 strategy: fail-fast: false matrix: include: - - destination: "OS=16.1,name=iPhone 14 Pro" - name: "iOS" - scheme: "Log" - sdk: iphonesimulator - - destination: "OS=16.1,name=Apple TV" - name: "tvOS" - scheme: "Log" - sdk: appletvsimulator - - destination: "OS=9.1,name=Apple Watch Series 8 (45mm)" - name: "watchOS" - scheme: "Log" - sdk: watchsimulator - - destination: "platform=macOS" - name: "macOS" - scheme: "Log" - sdk: macosx + - destination: "OS=10.0,name=Apple Watch Series 9 (45mm)" + name: "watchOS 10.0" + xcode: "Xcode_15.0" + runsOn: macos-13 + - destination: "OS=9.4,name=Apple Watch Series 8 (45mm)" + name: "watchOS 9.4" + xcode: "Xcode_14.3.1" + runsOn: macos-13 steps: - uses: actions/checkout@v3 - name: ${{ matrix.name }} - run: xcodebuild test -scheme "${{ matrix.scheme }}" -destination "${{ matrix.destination }}" clean -enableCodeCoverage YES -resultBundlePath "./${{ matrix.sdk }}.xcresult" | xcpretty -r junit + run: xcodebuild test -scheme "Log" -destination "${{ matrix.destination }}" clean -enableCodeCoverage YES -resultBundlePath "test_output/${{ matrix.name }}.xcresult" || exit 1 - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v3.1.0 with: token: ${{ secrets.CODECOV_TOKEN }} xcode: true - xcode_archive_path: "./${{ matrix.sdk }}.xcresult" - \ No newline at end of file + xcode_archive_path: test_output/${{ matrix.name }}.xcresult + - uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.name }} + path: test_output + + spm: + name: ${{ matrix.name }} + runs-on: ${{ matrix.runsOn }} + env: + DEVELOPER_DIR: "/Applications/${{ matrix.xcode }}.app/Contents/Developer" + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + include: + - name: "Xcode 15" + xcode: "Xcode_15.0" + runsOn: macos-13 + - name: "Xcode 14" + xcode: "Xcode_14.3.1" + runsOn: macos-13 + steps: + - uses: actions/checkout@v3 + - name: ${{ matrix.name }} + run: swift build -c release + + merge-test-reports: + needs: [iOS, macOS, watchOS, tvOS] + runs-on: macos-13 + steps: + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + path: test_output + - run: xcrun xcresulttool merge test_output/**/*.xcresult --output-path test_output/final/final.xcresult + - name: Upload Merged Artifact + uses: actions/upload-artifact@v4 + with: + name: MergedResult + path: test_output/final + + discover-typos: + name: Discover Typos + runs-on: macOS-12 + env: + DEVELOPER_DIR: /Applications/Xcode_14.1.app/Contents/Developer + steps: + - uses: actions/checkout@v2 + - name: Discover typos + run: | + export PATH="$PATH:/Library/Frameworks/Python.framework/Versions/3.11/bin" + python3 -m pip install --upgrade pip + python3 -m pip install codespell + codespell --ignore-words-list="hart,inout,msdos,sur" --skip="./.build/*,./.git/*" \ No newline at end of file diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index 1a0ab52..158ca87 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -15,7 +15,7 @@ jobs: - name: ruby setup uses: ruby/setup-ruby@v1 with: - ruby-version: 2.7 + ruby-version: 3.1.4 bundler-cache: true - name: Checkout code uses: actions/checkout@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 259b66b..ddaa57c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log All notable changes to this project will be documented in this file. +## [Unreleased] +#### Added +- Update GitHub Actions workflow + - Added in Pull Request [#3](https://github.com/space-code/log/pull/3). + #### 1.x Releases - `1.0.x` Releases - [1.0.0](#100) diff --git a/Package@swift-5.8.swift b/Package@swift-5.8.swift new file mode 100644 index 0000000..6de492d --- /dev/null +++ b/Package@swift-5.8.swift @@ -0,0 +1,24 @@ +// swift-tools-version: 5.8 +// The swift-tools-version declares the minimum version of Swift required to build this package. +// swiftlint:disable all + +import PackageDescription + +let package = Package( + name: "Log", + platforms: [ + .macOS(.v10_15), + .iOS(.v13), + .watchOS(.v7), + .tvOS(.v13), + ], + products: [ + .library(name: "Log", targets: ["Log"]), + ], + dependencies: [], + targets: [ + .target(name: "Log", dependencies: []), + .testTarget(name: "LogTests", dependencies: ["Log"]), + ] +) +// swiftlint:enable all diff --git a/Sources/Log/Classes/Core/Logger/Logger.swift b/Sources/Log/Classes/Core/Logger/Logger.swift index 8405788..b6a0a22 100644 --- a/Sources/Log/Classes/Core/Logger/Logger.swift +++ b/Sources/Log/Classes/Core/Logger/Logger.swift @@ -41,7 +41,7 @@ open class Logger { printers.forEach { $0.log(message, logLevel: logLevel) } } - /// Checks if the given `LogLevel` is allowed by the reciever. + /// Checks if the given `LogLevel` is allowed by the receiver. /// /// - Parameter logLevel: The log level to check. private func isLoggerEnabled(for logLevel: LogLevel) -> Bool { From 9ada899bd75ce386df0cb6a287a7b92c66a7520e Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Fri, 19 Jan 2024 08:08:53 +0100 Subject: [PATCH 4/7] Hide `IOSWriter` & `IConsoleWriter` from the public interface (#2) * Hide some implementation details * Update `CHANGELOG.md` * Add a test The test just checks that the methods don't cause a crash when printing a message to different outputs. * Update `codecov.yml` --- CHANGELOG.md | 2 + .../Core/Printers/ConsolePrinter.swift | 15 +++- .../Log/Classes/Core/Printers/OSPrinter.swift | 37 +++++----- .../Writers/ConsoleWriter/ConsoleWriter.swift | 8 +-- .../ConsoleWriter/IConsoleWriter.swift | 4 +- .../Helpers/Writers/OSWriter/IOSWriter.swift | 8 +-- .../Helpers/Writers/OSWriter/OSWriter.swift | 61 ++++++++++++++-- .../Strategies/IOSWriterStrategy.swift | 27 +++++++ .../LogIntegrationTests.swift | 70 +++++++++++++++++++ Tests/LogTests/Mocks/ConsoleWriterMock.swift | 4 +- Tests/LogTests/Mocks/OSWriterMock.swift | 14 ++-- .../UnitTests/ConsolePrinterTests.swift | 4 +- Tests/LogTests/UnitTests/OSPrinterTests.swift | 16 ++--- codecov.yml | 2 +- 14 files changed, 213 insertions(+), 59 deletions(-) create mode 100644 Sources/Log/Classes/Helpers/Writers/OSWriter/Strategies/IOSWriterStrategy.swift create mode 100644 Tests/LogTests/IntegrationTests/LogIntegrationTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index ddaa57c..b054eea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file. #### Added - Update GitHub Actions workflow - Added in Pull Request [#3](https://github.com/space-code/log/pull/3). +- Hide `IOSWriter` & `IConsoleWriter` from the public interface + - Added in Pull Request [#2](https://github.com/space-code/log/pull/2). #### 1.x Releases - `1.0.x` Releases - [1.0.0](#100) diff --git a/Sources/Log/Classes/Core/Printers/ConsolePrinter.swift b/Sources/Log/Classes/Core/Printers/ConsolePrinter.swift index 103e162..cb3018d 100644 --- a/Sources/Log/Classes/Core/Printers/ConsolePrinter.swift +++ b/Sources/Log/Classes/Core/Printers/ConsolePrinter.swift @@ -1,6 +1,6 @@ // // log -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation @@ -15,16 +15,25 @@ public final class ConsolePrinter { public let formatters: [ILogFormatter] /// The console writer. - public let consoleWriter: IConsoleWriter + private let consoleWriter: IConsoleWriter // MARK: Initialization + /// Creates a new `ConsolePrinter` instance. + /// + /// - Parameters: + /// - formatters: An array of log formatters for customizing log messages. + public init(formatters: [ILogFormatter]) { + self.formatters = formatters + consoleWriter = ConsoleWriter() + } + /// Creates a new `ConsolePrinter` instance. /// /// - Parameters: /// - formatters: An array of log formatters for customizing log messages. /// - consoleWriter: The console writer. - public init(formatters: [ILogFormatter], consoleWriter: IConsoleWriter = ConsoleWriter()) { + init(formatters: [ILogFormatter], consoleWriter: IConsoleWriter) { self.formatters = formatters self.consoleWriter = consoleWriter } diff --git a/Sources/Log/Classes/Core/Printers/OSPrinter.swift b/Sources/Log/Classes/Core/Printers/OSPrinter.swift index 1964c56..10bcb55 100644 --- a/Sources/Log/Classes/Core/Printers/OSPrinter.swift +++ b/Sources/Log/Classes/Core/Printers/OSPrinter.swift @@ -1,6 +1,6 @@ // // log -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation @@ -14,15 +14,9 @@ public final class OSPrinter { /// An array of log formatters used to customize log message output. public let formatters: [ILogFormatter] - /// The optional subsystem for categorizing log messages. - public let subsystem: String - /// The optional category for categorizing log messages. - public let category: String - /// The os writer. - public let osWriter: IOSWriter - /// An internal lazy property for initializing the OSLog instance. - private lazy var osLog: OSLog = .init(subsystem: subsystem, category: category) + /// An os writer. + private let osWriter: IOSWriter // MARK: Initialization @@ -32,15 +26,24 @@ public final class OSPrinter { /// - subsystem: An optional subsystem for categorizing log messages. /// - category: An optional category for categorizing log messages. /// - formatters: An array of log formatters for customizing log messages. - /// - osWriter: An os writer. public init( - subsystem: String = "os_printer", - category: String = "", - formatters: [ILogFormatter], - osWriter: IOSWriter = OSWriter() + subsystem: String, + category: String, + formatters: [ILogFormatter] ) { - self.subsystem = subsystem - self.category = category + self.formatters = formatters + osWriter = OSWriter( + subsystem: subsystem, + category: category + ) + } + + /// Creates a new `OSPrinter` instance. + /// + /// - Parameters: + /// - formatters: An array of log formatters for customizing log messages. + /// - osWriter: An os writer. + init(formatters: [ILogFormatter], osWriter: IOSWriter) { self.formatters = formatters self.osWriter = osWriter } @@ -52,7 +55,7 @@ extension OSPrinter: IStyleLogStrategy { public func log(_ message: String, logLevel: LogLevel) { let message = formatMessage(message, logLevel: logLevel) let type = sysLogPriority(logLevel) - osWriter.log("%s", log: osLog, type: type, message) + osWriter.log(type: type, message) } } diff --git a/Sources/Log/Classes/Helpers/Writers/ConsoleWriter/ConsoleWriter.swift b/Sources/Log/Classes/Helpers/Writers/ConsoleWriter/ConsoleWriter.swift index 1549580..adaf162 100644 --- a/Sources/Log/Classes/Helpers/Writers/ConsoleWriter/ConsoleWriter.swift +++ b/Sources/Log/Classes/Helpers/Writers/ConsoleWriter/ConsoleWriter.swift @@ -1,6 +1,6 @@ // // log -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation @@ -8,15 +8,15 @@ import Foundation // MARK: - ConsoleWriter /// A class that conforms to the IConsoleWriter protocol and writes messages to the console output. -public final class ConsoleWriter: IConsoleWriter { +final class ConsoleWriter: IConsoleWriter { // MARK: Initialization /// Initializes a new ConsoleWriter instance. - public init() {} + init() {} // MARK: IConsoleWriter - public func print(_ message: String) { + func print(_ message: String) { Swift.print(message) } } diff --git a/Sources/Log/Classes/Helpers/Writers/ConsoleWriter/IConsoleWriter.swift b/Sources/Log/Classes/Helpers/Writers/ConsoleWriter/IConsoleWriter.swift index 09d5a93..b0b5b6c 100644 --- a/Sources/Log/Classes/Helpers/Writers/ConsoleWriter/IConsoleWriter.swift +++ b/Sources/Log/Classes/Helpers/Writers/ConsoleWriter/IConsoleWriter.swift @@ -1,12 +1,12 @@ // // log -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation /// A protocol for writing messages to the console. -public protocol IConsoleWriter { +protocol IConsoleWriter { /// Prints a message to the console output. /// /// - Parameter message: The message to be printed as a String. diff --git a/Sources/Log/Classes/Helpers/Writers/OSWriter/IOSWriter.swift b/Sources/Log/Classes/Helpers/Writers/OSWriter/IOSWriter.swift index ec2fcab..29aa5f9 100644 --- a/Sources/Log/Classes/Helpers/Writers/OSWriter/IOSWriter.swift +++ b/Sources/Log/Classes/Helpers/Writers/OSWriter/IOSWriter.swift @@ -1,6 +1,6 @@ // // log -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation @@ -11,9 +11,7 @@ public protocol IOSWriter { /// Writes a log message to the specified OSLog. /// /// - Parameters: - /// - message: A StaticString containing the log message format. - /// - log: An OSLog object representing the log subsystem and category. /// - type: An OSLogType indicating the log message type. - /// - args: A variadic list of CVarArg values to fill in the message format. - func log(_ message: StaticString, log: OSLog, type: OSLogType, _ args: CVarArg...) + /// - message: A variadic list of String values to fill in the message format. + func log(type: OSLogType, _ message: String) } diff --git a/Sources/Log/Classes/Helpers/Writers/OSWriter/OSWriter.swift b/Sources/Log/Classes/Helpers/Writers/OSWriter/OSWriter.swift index a4ad3ad..8af506b 100644 --- a/Sources/Log/Classes/Helpers/Writers/OSWriter/OSWriter.swift +++ b/Sources/Log/Classes/Helpers/Writers/OSWriter/OSWriter.swift @@ -1,6 +1,6 @@ // // log -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation @@ -8,16 +8,63 @@ import OSLog // MARK: - OSWriter -/// A class that conforms to the IOSWriter protocol and writes log messages to the Apple OSLog system. -public final class OSWriter: IOSWriter { +final class OSWriter: IOSWriter { + // MARK: Properties + + /// The optional subsystem for categorizing log messages. + private let subsystem: String + /// The optional category for categorizing log messages. + private let category: String + + /// An internal lazy property for initializing the OSLog instance. + private var osLog: OSLog { OSLog(subsystem: subsystem, category: category) } + + /// An internal lazy property for initializing WriteStrategy instance. + private lazy var writerStrategy: IOSWriterStrategy = { + if #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) { + return os.Logger(osLog) + } else { + return LegacyOSLogger(osLog: osLog) + } + }() + // MARK: Initialization - /// Creates a new `OSWriter` instance. - public init() {} + /// Creates a `OSWriter` instance. + /// + /// - Parameters: + /// - subsystem: An optional subsystem for categorizing log messages. + /// - category: An optional category for categorizing log messages. + init(subsystem: String, category: String) { + self.subsystem = subsystem + self.category = category + } // MARK: IOSWriter - public func log(_ message: StaticString, log: OSLog, type: OSLogType, _ args: CVarArg...) { - os_log(message, log: log, type: type, args) + func log(type: OSLogType, _ message: String) { + writerStrategy.log(type: type, message) + } +} + +// MARK: OSWriter.LegacyOSLogger + +private extension OSWriter { + struct LegacyOSLogger: IOSWriterStrategy { + // MARK: Private + + private let osLog: OSLog + + // MARK: Initialization + + init(osLog: OSLog) { + self.osLog = osLog + } + + // MARK: IOSWriterStrategy + + func log(type: OSLogType, _ message: String) { + os_log("%s", log: osLog, type: type, message) + } } } diff --git a/Sources/Log/Classes/Helpers/Writers/OSWriter/Strategies/IOSWriterStrategy.swift b/Sources/Log/Classes/Helpers/Writers/OSWriter/Strategies/IOSWriterStrategy.swift new file mode 100644 index 0000000..bb8f3ed --- /dev/null +++ b/Sources/Log/Classes/Helpers/Writers/OSWriter/Strategies/IOSWriterStrategy.swift @@ -0,0 +1,27 @@ +// +// log +// Copyright © 2024 Space Code. All rights reserved. +// + +import os + +// MARK: - IOSWriterStrategy + +/// Protocol defining the contract for a logger strategy that writes logs to the iOS system logs using OSLog. +protocol IOSWriterStrategy { + /// Writes a log message to the iOS system logs with the specified log type. + /// + /// - Parameters: + /// - type: The type of the log message (debug, info, error, etc.). + /// - message: The message to be logged. + func log(type: OSLogType, _ message: String) +} + +// MARK: - os.Logger + IOSWriterStrategy + +@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) +extension os.Logger: IOSWriterStrategy { + func log(type: OSLogType, _ message: String) { + log(level: type, "\(message)") + } +} diff --git a/Tests/LogTests/IntegrationTests/LogIntegrationTests.swift b/Tests/LogTests/IntegrationTests/LogIntegrationTests.swift new file mode 100644 index 0000000..c87b149 --- /dev/null +++ b/Tests/LogTests/IntegrationTests/LogIntegrationTests.swift @@ -0,0 +1,70 @@ +// +// log +// Copyright © 2024 Space Code. All rights reserved. +// + +import Log +import XCTest + +// MARK: - LogIntegrationTests + +final class LogIntegrationTests: XCTestCase { + // MARK: Properties + + private var sut: Logger! + + // MARK: XCTestCase + + override func setUp() { + super.setUp() + let formatters: [ILogFormatter] = [ + TimestampLogFormatter(dateFormat: "dd/MM/yyyy"), + PrefixLogFormatter(name: "LogIntegrationTests"), + ] + + sut = Logger( + printers: [ + ConsolePrinter( + formatters: formatters + ), + OSPrinter( + subsystem: .subsystem, + category: .category, + formatters: formatters + ), + ], + logLevel: .all + ) + } + + override func tearDown() { + sut = nil + super.tearDown() + } + + // MARK: Tests + + // The test just checks that the methods don't cause a crash + // when printing a message to different outputs. + func test_logDoesNotThrowUnexpectedBehavior_whenLogMessages() { + // 1. Print an info message + sut.info(message: .message) + + // 2. Print a debug message + sut.debug(message: .message) + + // 3. Print an error message + sut.error(message: .message) + + // 4. Print a fault message + sut.fault(message: .message) + } +} + +// MARK: - Constants + +private extension String { + static let subsystem = "subsystem" + static let category = "category" + static let message = "text" +} diff --git a/Tests/LogTests/Mocks/ConsoleWriterMock.swift b/Tests/LogTests/Mocks/ConsoleWriterMock.swift index 7b0cec8..620f81b 100644 --- a/Tests/LogTests/Mocks/ConsoleWriterMock.swift +++ b/Tests/LogTests/Mocks/ConsoleWriterMock.swift @@ -1,10 +1,10 @@ // // log -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Foundation -import Log +@testable import Log final class ConsoleWriterMock: IConsoleWriter { var invokedPrint = false diff --git a/Tests/LogTests/Mocks/OSWriterMock.swift b/Tests/LogTests/Mocks/OSWriterMock.swift index 165dc09..0d00eb1 100644 --- a/Tests/LogTests/Mocks/OSWriterMock.swift +++ b/Tests/LogTests/Mocks/OSWriterMock.swift @@ -1,21 +1,21 @@ // // log -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // -import Log +@testable import Log import OSLog final class OSWriterMock: IOSWriter { var invokedLog = false var invokedLogCount = 0 - var invokedLogParameters: (message: StaticString, log: OSLog, type: OSLogType, args: CVarArg)? - var invokedLogParametersList = [(message: StaticString, log: OSLog, type: OSLogType, args: CVarArg)]() + var invokedLogParameters: (type: OSLogType, message: String)? + var invokedLogParametersList = [(type: OSLogType, message: String)]() - func log(_ message: StaticString, log: OSLog, type: OSLogType, _ args: CVarArg...) { + func log(type: OSLogType, _ message: String) { invokedLog = true invokedLogCount += 1 - invokedLogParameters = (message, log, type, args) - invokedLogParametersList.append((message, log, type, args)) + invokedLogParameters = (type, message) + invokedLogParametersList.append((type, message)) } } diff --git a/Tests/LogTests/UnitTests/ConsolePrinterTests.swift b/Tests/LogTests/UnitTests/ConsolePrinterTests.swift index 4478dfd..c14640a 100644 --- a/Tests/LogTests/UnitTests/ConsolePrinterTests.swift +++ b/Tests/LogTests/UnitTests/ConsolePrinterTests.swift @@ -1,9 +1,9 @@ // // log -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // -import Log +@testable import Log import XCTest // MARK: - ConsolePrinterTests diff --git a/Tests/LogTests/UnitTests/OSPrinterTests.swift b/Tests/LogTests/UnitTests/OSPrinterTests.swift index f4175a5..d3a69fd 100644 --- a/Tests/LogTests/UnitTests/OSPrinterTests.swift +++ b/Tests/LogTests/UnitTests/OSPrinterTests.swift @@ -1,9 +1,9 @@ // // log -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // -import Log +@testable import Log import XCTest // MARK: - OSPrinterTests @@ -23,8 +23,6 @@ final class OSPrinterTests: XCTestCase { formatterMock = LogFormatterMock() osWriterMock = OSWriterMock() sut = OSPrinter( - subsystem: .subsystem, - category: .category, formatters: [formatterMock], osWriter: osWriterMock ) @@ -47,7 +45,7 @@ final class OSPrinterTests: XCTestCase { sut.log(.message, logLevel: .all) // then - XCTAssertEqual((osWriterMock.invokedLogParameters?.args as? [String])?.first, .message) + XCTAssertEqual(osWriterMock.invokedLogParameters?.message, .message) } func test_thatConsolePrinterLogsMessage_whenLogLevelIsDebug() { @@ -58,7 +56,7 @@ final class OSPrinterTests: XCTestCase { sut.log(.message, logLevel: .debug) // then - XCTAssertEqual((osWriterMock.invokedLogParameters?.args as? [String])?.first, .message) + XCTAssertEqual(osWriterMock.invokedLogParameters?.message, .message) } func test_thatConsolePrinterLogsMessage_whenLogLevelIsInfo() { @@ -69,7 +67,7 @@ final class OSPrinterTests: XCTestCase { sut.log(.message, logLevel: .info) // then - XCTAssertEqual((osWriterMock.invokedLogParameters?.args as? [String])?.first, .message) + XCTAssertEqual(osWriterMock.invokedLogParameters?.message, .message) } func test_thatConsolePrinterLogsMessage_whenLogLevelIsError() { @@ -80,7 +78,7 @@ final class OSPrinterTests: XCTestCase { sut.log(.message, logLevel: .error) // then - XCTAssertEqual((osWriterMock.invokedLogParameters?.args as? [String])?.first, .message) + XCTAssertEqual(osWriterMock.invokedLogParameters?.message, .message) } func test_thatConsolePrinterLogsMessage_whenLogLevelIsFault() { @@ -91,7 +89,7 @@ final class OSPrinterTests: XCTestCase { sut.log(.message, logLevel: .fault) // then - XCTAssertEqual((osWriterMock.invokedLogParameters?.args as? [String])?.first, .message) + XCTAssertEqual(osWriterMock.invokedLogParameters?.message, .message) } } diff --git a/codecov.yml b/codecov.yml index b415604..8bb858a 100644 --- a/codecov.yml +++ b/codecov.yml @@ -32,7 +32,7 @@ coverage: target: 85% # Allow coverage to drop by X% - threshold: 5% + threshold: 50% changes: no comment: From 941be4d17fc0ae83b9e2d26e2cf9b58ebd5a7d85 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Fri, 19 Jan 2024 09:39:52 +0100 Subject: [PATCH 5/7] Add files to comply with community standards (#4) * Add files to comply with community standards - Add `CODE_OF_CONDUCT.md` - Add `CONTRIBUTING.md` - Add `SECURITY.md` - Update templates * Update `CHANGELOG.md` * Update `README.md` --- .../{bug_template.yml => bug_template.md} | 0 ...ature_template.yml => feature_template.md} | 0 CHANGELOG.md | 2 + CODE_OF_CONDUCT.md | 74 +++++++++++++++++++ CONTRIBUTING.md | 61 +++++++++++++++ README.md | 6 +- SECURITY.md | 7 ++ 7 files changed, 148 insertions(+), 2 deletions(-) rename .github/PULL_REQUEST_TEMPLATE/{bug_template.yml => bug_template.md} (100%) rename .github/PULL_REQUEST_TEMPLATE/{feature_template.yml => feature_template.md} (100%) create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 SECURITY.md diff --git a/.github/PULL_REQUEST_TEMPLATE/bug_template.yml b/.github/PULL_REQUEST_TEMPLATE/bug_template.md similarity index 100% rename from .github/PULL_REQUEST_TEMPLATE/bug_template.yml rename to .github/PULL_REQUEST_TEMPLATE/bug_template.md diff --git a/.github/PULL_REQUEST_TEMPLATE/feature_template.yml b/.github/PULL_REQUEST_TEMPLATE/feature_template.md similarity index 100% rename from .github/PULL_REQUEST_TEMPLATE/feature_template.yml rename to .github/PULL_REQUEST_TEMPLATE/feature_template.md diff --git a/CHANGELOG.md b/CHANGELOG.md index b054eea..0131ae9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] #### Added +- Add files to comply with community standards + - Added in Pull Request [#4](https://github.com/space-code/log/pull/4). - Update GitHub Actions workflow - Added in Pull Request [#3](https://github.com/space-code/log/pull/3). - Hide `IOSWriter` & `IConsoleWriter` from the public interface diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..56c1661 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting one of the project maintainers https://github.com/orgs/space-code/people. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..349d9ec --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,61 @@ +# Contributing Guidelines + +This document contains information and guidelines about contributing to this project. +Please read it before you start participating. + +**Topics** + +* [Reporting Issues](#reporting-issues) +* [Submitting Pull Requests](#submitting-pull-requests) +* [Developers Certificate of Origin](#developers-certificate-of-origin) +* [Code of Conduct](#code-of-conduct) + +## Reporting Issues + +A great way to contribute to the project is to send a detailed issue when you encounter a problem. We always appreciate a well-written, thorough bug report. + +Check that the project issues database doesn't already include that problem or suggestion before submitting an issue. If you find a match, feel free to vote for the issue by adding a reaction. Doing this helps prioritize the most common problems and requests. + +When reporting issues, please fill out our issue template. The information the template asks for will help us review and fix your issue faster. + +## Submitting Pull Requests + +You can contribute by fixing bugs or adding new features. For larger code changes, we recommend first discussing your ideas on our [GitHub Discussions](https://github.com/space-code/log/discussions). When submitting a pull request, please add relevant tests and ensure your changes don't break any existing tests. + +## Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +- (a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +- (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +- (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +- (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. + +## Code of Conduct + +The Code of Conduct governs how we behave in public or in private +whenever the project will be judged by our actions. +We expect it to be honored by everyone who contributes to this project. + +See [CODE_OF_CONDUCT.md](https://github.com/space-code/log/blob/master/CODE_OF_CONDUCT.md) for details. + +--- + +*Some of the ideas and wording for the statements above were based on work by the [Docker](https://github.com/docker/docker/blob/master/CONTRIBUTING.md) and [Linux](https://elinux.org/Developer_Certificate_Of_Origin) communities. \ No newline at end of file diff --git a/README.md b/README.md index 03b197d..d3d5638 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,13 @@

License -Platform -5.7 +Swift Compatibility +Platform Compatibility CI CodeCov +GitHub release; latest by date +GitHub commit activity

## Description diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..20dffca --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,7 @@ +# Reporting Security Vulnerabilities + +This software is built with security and data privacy in mind to ensure your data is safe. We are grateful for security researchers and users reporting a vulnerability to us, first. To ensure that your request is handled in a timely manner and non-disclosure of vulnerabilities can be assured, please follow the below guideline. + +**Please do not report security vulnerabilities directly on GitHub. GitHub Issues can be publicly seen and therefore would result in a direct disclosure.** + +* Please address questions about data privacy, security concepts, and other media requests to the nv3212@gmail.com mailbox. \ No newline at end of file From 6f1776309ede4d5cf6c2e590a7d17dd12d7cfe51 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Fri, 19 Jan 2024 10:54:07 +0100 Subject: [PATCH 6/7] Make the `logLevel` property changeable (#5) * Make the `logLevel` property changable * Update `CHANGELOG.md` --- .swiftlint.yml | 1 - CHANGELOG.md | 2 + Sources/Log/Classes/Core/Logger/Logger.swift | 15 +++++-- .../Log/Classes/Helpers/Atomic/Atomic.swift | 43 +++++++++++++++++++ Tests/LogTests/UnitTests/LogTests.swift | 17 +++++++- 5 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 Sources/Log/Classes/Helpers/Atomic/Atomic.swift diff --git a/.swiftlint.yml b/.swiftlint.yml index 6d90edc..58036d3 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -16,7 +16,6 @@ opt_in_rules: # some rules are only opt-in - attributes - closure_body_length - closure_end_indentation - - closure_spacing - collection_alignment - contains_over_filter_count - contains_over_filter_is_empty diff --git a/CHANGELOG.md b/CHANGELOG.md index 0131ae9..6d9f710 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] #### Added +- Make the `logLevel` property changeable + - Added in Pull Request [#5](https://github.com/space-code/log/pull/5). - Add files to comply with community standards - Added in Pull Request [#4](https://github.com/space-code/log/pull/4). - Update GitHub Actions workflow diff --git a/Sources/Log/Classes/Core/Logger/Logger.swift b/Sources/Log/Classes/Core/Logger/Logger.swift index b6a0a22..2af975c 100644 --- a/Sources/Log/Classes/Core/Logger/Logger.swift +++ b/Sources/Log/Classes/Core/Logger/Logger.swift @@ -1,8 +1,10 @@ // // log -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // +import Foundation + // MARK: - Logger /// A class responsible for logging functionality. @@ -10,7 +12,14 @@ open class Logger { // MARK: Properties /// The current log level for this logger. - let logLevel: LogLevel + private var _logLevel: Atomic + + /// The current log level for this logger. + public var logLevel: LogLevel { + get { _logLevel.value } + set { _logLevel.value = newValue } + } + /// An array of printer strategies to handle the log output. let printers: [IPrinterStrategy] @@ -26,7 +35,7 @@ open class Logger { logLevel: LogLevel ) { self.printers = printers - self.logLevel = logLevel + _logLevel = Atomic(value: logLevel) } // MARK: Private diff --git a/Sources/Log/Classes/Helpers/Atomic/Atomic.swift b/Sources/Log/Classes/Helpers/Atomic/Atomic.swift new file mode 100644 index 0000000..6d0b4cb --- /dev/null +++ b/Sources/Log/Classes/Helpers/Atomic/Atomic.swift @@ -0,0 +1,43 @@ +// +// log +// Copyright © 2024 Space Code. All rights reserved. +// + +import Foundation + +// MARK: - Atomic + +/// The Atomic class is designed to provide thread-safe access to a mutable value. +final class Atomic { + // MARK: Properties + + /// NSLock instance for synchronization. + private let lock = NSLock() + /// The actual mutable value. + private var _value: Value + + /// Computed property to get and set the value atomically + var value: Value { + get { lock.synchronized { _value } } + set { lock.synchronized { _value = newValue }} + } + + // MARK: Initialization + + /// Initializes the Atomic instance with an initial value. + init(value: Value) { + _value = value + } +} + +// MARK: - Extensions + +private extension NSLock { + /// Synchronizes a code block using the NSLock instance. + /// This helps ensure that only one thread can access the critical section at a time. + func synchronized(block: () throws -> T) rethrows -> T { + lock() + defer { unlock() } + return try block() + } +} diff --git a/Tests/LogTests/UnitTests/LogTests.swift b/Tests/LogTests/UnitTests/LogTests.swift index 4284ac4..a9bf700 100644 --- a/Tests/LogTests/UnitTests/LogTests.swift +++ b/Tests/LogTests/UnitTests/LogTests.swift @@ -1,6 +1,6 @@ // // log -// Copyright © 2023 Space Code. All rights reserved. +// Copyright © 2024 Space Code. All rights reserved. // import Log @@ -119,6 +119,21 @@ final class LogTests: XCTestCase { XCTAssertNil(printerMock.invokedLogParameters?.message) } + func test_thatLoggerDoesNotPrintAnything_whenLogLevelValueDidChange() { + // given + let sut = prepareSut() + + // when + sut.logLevel = .info + sut.debug(message: .message) + sut.info(message: .message) + + // then + XCTAssertEqual(sut.logLevel, .info) + XCTAssertEqual(printerMock.invokedLogCount, 1) + XCTAssertEqual(printerMock.invokedLogParameters?.message, .message) + } + // MARK: Private private func prepareSut(logLevel: LogLevel = .all) -> Logger { From 7638bd1f9252d0822e38b74b0bf02f5bded94c96 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Fri, 19 Jan 2024 11:01:56 +0100 Subject: [PATCH 7/7] Update `CHANGELOG.md` (#6) --- CHANGELOG.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d9f710..aa07494 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,11 @@ # Change Log All notable changes to this project will be documented in this file. -## [Unreleased] +#### 1.x Releases +- `1.1.x` Releases - [1.1.0](#110) +- `1.0.x` Releases - [1.0.0](#100) + +## [1.1.0](https://github.com/space-code/log/releases/tag/1.1.0) #### Added - Make the `logLevel` property changeable - Added in Pull Request [#5](https://github.com/space-code/log/pull/5). @@ -12,9 +16,6 @@ All notable changes to this project will be documented in this file. - Hide `IOSWriter` & `IConsoleWriter` from the public interface - Added in Pull Request [#2](https://github.com/space-code/log/pull/2). -#### 1.x Releases -- `1.0.x` Releases - [1.0.0](#100) - ## [1.0.0](https://github.com/space-code/log/releases/tag/1.0.0) Released on 2023-10-18.