Apple's SwiftLog + OSLog style StringInterpolation

Related tags

Logging swift logging
Overview

ios tv watch mac

Logging

A version of Apple's SwiftLog that adds some improved formatting for app development and includes OSLog-ish string interpolation.

Feature List

  • Privacy (public, private and masked)
  • Log levels
  • FormattedLogHandler
  • Literal string
  • Numerical formats
  • Boolean formats
  • Exponential formats
  • Hexadecimal formats
  • Column formatting

I've also added many tests to ensure the string interpolation and privacy features are working as expected. However, I have not included any of SwiftLog's tests since the library is simply a direct copy (see below).

Examples

// Somewhere in your code, define your log handler(s)
LoggingSystem.bootstrap { label in 
    FormattedLogHandler(label: label)
}

// Then in a framework or subsystem, define a logger
let logger = Logger(label: "com.benkau.logging")
logger.debug("Hello, world!")

Similar to OSLog, all interpolated values default to a private scope (in a non-DEBUG) environment, with their values redacted.

logger.debug("Logged in as \(user, privacy: .private)")
// Logged in as <redacted>

logger.debug("Fetching data from \(url, privacy: .private(.hash))")
// Fetching data from 210237823

There are conveniences for logging numerical values:

logger.debug("Pi is \(3.14159265359, format: .fixed(precision: 2))")
// Pi is 3.14

logger.debug("Current score: \(score, format: .decimal(minDigits: 2)")
// Current score: 03

Formatting

The library includes a custom FormattedLogHandler that you're free to use or create your own. The provided handler uses SFSymbols to improve readability and clarity in the console, as well as providing a simple closure based formatter so you can make it your own.

FormattedLogHandler { options in 
    // simply return your formatted log
    FormattedLogHandler(label: label) { data in
        "\(data.timestamp()) [\(data.label)] \(data.level.symbol) \(data.message)"
    }
}

Obviously you can always use your own LogHandler as you can directly with SwiftLog.

SwiftLog

The actual logging framework is a direct copy of Apple's own SwiftLog. The reason I didn't include it as a dependency is because there was no way for me to extend it to include string interpolation that I could see. If anyone has ideas on how to make this work, I would love to hear about them. Please open an Issue so we can discuss it as this would allow me to properly attribute and pin to a dependency version etc...

Installation

The code is packaged as a framework. You can install manually (by copying the files in the Sources directory) or using Swift Package Manager (preferred)

To install using Swift Package Manager, add this to the dependencies section of your Package.swift file:

.package(url: "https://github.com/shaps80/Logging.git", .upToNextMinor(from: "1.0.0"))

Comments
  • Better fix for Issue #1 support for Swift compiler < 5.5

    Better fix for Issue #1 support for Swift compiler < 5.5

    More complete fix for Issue #1. Note commit comment about not including #if swift(<5.5) as a personal preference that you’re free to add if you prefer it be there.

    opened by GeekAndDad 5
  • Help new to the project person understand why tests are failing & what fix is

    Help new to the project person understand why tests are failing & what fix is

    Issue #2

    Describe your changes

    Since it's relatively unusual that testing must be done with a release build add a message with help for a new-to-the-project person to understand what they need to do to make tests run.

    Originally I had this just an XCTFail("…") message and let the rest of the asserts fail also, but decided it might be better to make the test not fail in debug builds because most projects that depend upon this will likely not want to run their automated testing on release builds so if they incorporate this package it'll break their automated builds. I can revert this last commit to make the PR from the previous commit if you prefer it breaking from the command line.

    opened by GeekAndDad 4
  • Test errors in Tests+Privacy.swift when running tests on the command line.

    Test errors in Tests+Privacy.swift when running tests on the command line.

    Below is the sample build log and sequence of commands I did on the command line where I see the errors.

    The log below is for the build is being done using the fixes in #3 so as to test Xcode 12.5.1 (Swift 5.4.2).

    Doing this build in Xcode 12.5.1 by opening the package folder and then running tests works without test failures.

    Likewise on main pre-PR-merged-branch, these tests succeed in Xcode 13.0 but fail on the command line.

    Logging % sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
    
    Logging % swift --version
    swift-driver version: 1.26.9 Apple Swift version 5.5 (swiftlang-1300.0.31.1 clang-1300.0.29.1)
    Target: arm64-apple-macosx11.0
    
    Logging % swift package clean 
    
    Logging % swift test
    [14/14] Build complete!
    Test Suite 'All tests' started at 2021-09-22 15:58:43.731
    Test Suite 'LoggingPackageTests.xctest' started at 2021-09-22 15:58:43.731
    Test Suite 'FloatTests' started at 2021-09-22 15:58:43.731
    Test Case '-[LoggingTests.FloatTests testFloats]' started.
    Test Case '-[LoggingTests.FloatTests testFloats]' passed (0.002 seconds).
    Test Suite 'FloatTests' passed at 2021-09-22 15:58:43.733.
    	 Executed 1 test, with 0 failures (0 unexpected) in 0.002 (0.002) seconds
    Test Suite 'IntegerTests' started at 2021-09-22 15:58:43.733
    Test Case '-[LoggingTests.IntegerTests testSigned]' started.
    Test Case '-[LoggingTests.IntegerTests testSigned]' passed (0.000 seconds).
    Test Case '-[LoggingTests.IntegerTests testUnsigned]' started.
    Test Case '-[LoggingTests.IntegerTests testUnsigned]' passed (0.000 seconds).
    Test Suite 'IntegerTests' passed at 2021-09-22 15:58:43.734.
    	 Executed 2 tests, with 0 failures (0 unexpected) in 0.000 (0.001) seconds
    Test Suite 'PrivateTests' started at 2021-09-22 15:58:43.734
    Test Case '-[LoggingTests.PrivateTests testPrivate]' started.
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:16: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("name") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:19: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("-3.141593") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:21: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("-3") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:23: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("+-3.141593") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:25: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("+-3") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:28: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("-3.141593") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:30: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("-3.141593") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:32: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("-3.1") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:34: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("+-3.141593") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:36: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("+-3.1") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:39: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("true") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:41: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("yes") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:43: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("true") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:46: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("mock") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:48: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("Mock") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:50: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("<NSObject: 0x13377fc60>") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:53: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("3") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:55: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("3") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:57: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("+3") is not equal to ("<redacted>")
    /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Private.swift:59: error: -[LoggingTests.PrivateTests testPrivate] : XCTAssertEqual failed: ("+3") is not equal to ("<redacted>")
    Test Case '-[LoggingTests.PrivateTests testPrivate]' failed (0.239 seconds).
    Test Suite 'PrivateTests' failed at 2021-09-22 15:58:43.972.
    	 Executed 1 test, with 20 failures (0 unexpected) in 0.239 (0.239) seconds
    Test Suite 'PublicTests' started at 2021-09-22 15:58:43.972
    Test Case '-[LoggingTests.PublicTests testPublic]' started.
    Test Case '-[LoggingTests.PublicTests testPublic]' passed (0.000 seconds).
    Test Suite 'PublicTests' passed at 2021-09-22 15:58:43.972.
    	 Executed 1 test, with 0 failures (0 unexpected) in 0.000 (0.000) seconds
    Test Suite 'LoggingPackageTests.xctest' failed at 2021-09-22 15:58:43.973.
    	 Executed 5 tests, with 20 failures (0 unexpected) in 0.241 (0.241) seconds
    Test Suite 'All tests' failed at 2021-09-22 15:58:43.973.
    	 Executed 5 tests, with 20 failures (0 unexpected) in 0.241 (0.242) seconds
    
    bug 
    opened by GeekAndDad 3
  • fix #2 via a property settable in tests.

    fix #2 via a property settable in tests.

    Issue #2

    Describe your changes

    From the commit: Alternate method of fixing this issue which allows tests to run in both Release or Debug configurations via a new DEBUG build only configuration variable in LogPrivacy which may be set in tests.

    opened by GeekAndDad 1
  • Document cross-module usage

    Document cross-module usage

    It's probably worth providing an example for how best to use the Logging framework across multiple modules (including an App, its extensions and packages).

    opened by shaps80 0
  • Fixes #1 - Allow code to build for Swift compilers <5.5

    Fixes #1 - Allow code to build for Swift compilers <5.5

    Interchangable use of CGFloat and Double isn't supported until Swift 5.5:

    https://github.com/apple/swift-evolution/blob/main/proposals/0307-allow-interchangeable-use-of-double-cgfloat-types.md

    Addes #if swift(<5.5) conditional to allow compiling in older Swift versions.

    Note: Only ran the tests on macOS 11.5.2. All Test+Float tests pass in Swift 5.4.2 with this change, and it compiles in both 5.4.2 and 5.5, but there's a test assertion failure in Swift 5.5 (release version with Xcode 13.0). That's a separate issue.

    Fix for issue #1

    Added conditional test for swift version and construct a Double manually on swift compiler versions less than 5.5.

    Note: This PR doesn’t address project’s other failing tests in Test+Private.swift in Swift 5.5 and 5.4.2 even with this fix. Those filed as #2

    opened by GeekAndDad 0
  • Swift compiler <5.5 has compile failure in Float+Test.swift

    Swift compiler <5.5 has compile failure in Float+Test.swift

    All testing was done on 13" M1 MBP running macOS 11.5.2

    Local testing done with:

    • Xcode 13.0 (release version); Swift 5.5

    • Xcode 12.5.1 (last released version); Swift 5.4.2

    • Devices: M1 13" MBP

    Describe the bug

    Build error on lines 22, 67, 72 of Tes+Floats.swift when compiling with Swift 5.4.2 (Xcode 12.5.1)

    Steps to reproduce

    1. sudo xcode-select -s /Applications/Xcode-12.5.1.app/Contents/Developer/
    2. cd [directory for package]
    3. swift test

    Expected behavior

    Builds and all tests pass.

    Stack trace, compiler error, code

    > Logging % swift test
    > /Users/Shared/OpenSource/Logging/Tests/LoggingTests/Test+Floats.swift:22:24: error: no exact matches in call to instance method 'appendInterpolation'
    >         logger.debug("\(value, format: .fixed(precision: 2), privacy: .public)")
    >                        ^
    > /Users/Shared/OpenSource/Logging/Sources/Logging/Interpolation.swift:67:26: note: candidate expects value of type 'Float' for parameter #1
    >     public mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Float, format: LogFloatFormatting = .fixed, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) {
    >                          ^
    > /Users/Shared/OpenSource/Logging/Sources/Logging/Interpolation.swift:72:26: note: candidate expects value of type 'Double' for parameter #1
    >     public mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Double, format: LogFloatFormatting = .fixed, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) {
    >                          ^
    > [12/13] Compiling LoggingTests Test+Public.swift
    > error: fatalError
    > 
    
    

    PR to fix these build errors to be provided shortly.

    bug 
    opened by GeekAndDad 0
Owner
Shaps
Engineer @thirdfort ● Previously @EverythingSet @thread @F1 @BleepBleeps @theappbusiness @tfl @Playboy more... ● I love to build tools for the world
Shaps
🐵Fooling around with Apples private framework AvatarKit

Fooling around with Apples private framework AvatarKit, the framework used in Messages.app for recording Animoji videos. If you are looking to create your own Animoji, take a look at SBSCustomAnimoji.

Simon Støvring 968 Dec 25, 2022
Sentry logging backend for SwiftLog

SwiftLogSentry A Sentry logging backend for SwiftLog, it works by creating and adding a Breadcrumb for log events. Features Supports metadata by inser

Eric Lewis 3 Nov 22, 2022
Lightweight utilities for making OSLog more pleasant

UnifiedLoggingPlus Lightweight utilities for making OSLog more pleasant. Integration Swift Package Manager

Chime 10 Oct 26, 2022
SwiftLint - A tool to enforce Swift style and conventions, loosely based on Swift Style Guide.

SwiftLint - A tool to enforce Swift style and conventions, loosely based on Swift Style Guide.

Realm 16.9k Dec 30, 2022
Style Art library process images using COREML with a set of pre trained machine learning models and convert them to Art style.

StyleArt Style Art is a library that process images using COREML with a set of pre trained machine learning models and convert them to Art style. Prev

iLeaf Solutions Pvt. Ltd. 222 Dec 17, 2022
Airbnb's Swift Style Guide.

Airbnb Swift Style Guide Goals Following this style guide should: Make it easier to read and begin understanding unfamiliar code. Make code easier to

Airbnb 1.8k Jan 3, 2023
LinkedIn's Official Swift Style Guide

Swift Style Guide Make sure to read Apple's API Design Guidelines. Specifics from these guidelines + additional remarks are mentioned below. This guid

LinkedIn 1.4k Jan 5, 2023
The Official raywenderlich.com Swift Style Guide.

The Official raywenderlich.com Swift Style Guide. Updated for Swift 5 This style guide is different from others you may see, because the focus is cent

raywenderlich 12.5k Jan 3, 2023
Arrow 🏹 Parse JSON with style

Arrow ?? Parse JSON with style

Fresh 376 Nov 8, 2022
Rough lets you draw in a sketchy, hand-drawn-like, style.

Rough (Swift) Rough lets you draw in a sketchy, hand-drawn-like, style. It is Swift clone of Rough.js. The library defines primitives to draw lines, c

null 96 Nov 24, 2022
A tool to enforce Swift style and conventions.

SwiftLint A tool to enforce Swift style and conventions, loosely based on the now archived GitHub Swift Style Guide. SwiftLint enforces the style guid

Realm 16.9k Jan 9, 2023
💾 A collection of classic-style UI components for iOS

A collection of classic-style UI components for UIKit, influenced by Windows 95 Introduction This is a little exploration into applying '90s-era desig

Blake Tsuzaki 2.2k Dec 22, 2022
Kit for building custom gauges + easy reproducible Apple's style ring gauges.

GaugeKit ##Kit for building custom gauges + easy reproducible Apple's style ring gauges. -> Example Usage Open GaugeKit.xcworkspace and change the sch

Petr Korolev 1k Dec 23, 2022
A simple style messages/notifications, in Swift.

Demo Example To show notifications use the following code: self.showMessage("Something success", type: .success) To display a notice on a view: view.s

Gesen 704 Dec 17, 2022
A simple, customizable popup dialog for iOS written in Swift. Replaces UIAlertController alert style.

Introduction Popup Dialog is a simple, customizable popup dialog written in Swift. Features Easy to use API with hardly any boilerplate code Convenien

Orderella Ltd. 3.8k Dec 20, 2022
Elegant Apply Style by Swift Method Chain.🌙

ApplyStyleKit ApplyStyleKit is a library that applies styles to UIKit using Swifty Method Chain. Normally, when applying styles to UIView etc.,it is n

shindyu 203 Nov 22, 2022
A fully customizable popup style menu for iOS 😎

Guide Check out the documentation and guides for details on how to use. (Available languages:) English 简体中文 What's a better way to know what PopMenu o

Cali Castle 1.5k Dec 30, 2022
Demonstrates hosting SwiftUI in a UISplitViewController to gain the sidebar style in Mac Catalyst

Really trivial example showing how to wrap SwiftUI in a UISplitViewController, so that you can use the correct sidebar background style when building for macOS.

Steven Troughton-Smith 68 Oct 26, 2022
BDD-style framework for Swift

Sleipnir Sleipnir is a BDD-style framework for Swift. Sleipnir is highly inspired by Cedar. Also In Norse mythology, Sleipnir is Odin's steed, is the

Railsware 846 Nov 22, 2022
TextMate-style syntax highlighting

SyntaxKit SyntaxKit makes TextMate-style syntax highlighting easy. It works on iOS, watchOS, and OS X. SyntaxKit was abstracted from Whiskey. Building

Sam Soffes 466 Sep 9, 2022