Skip to content

SwiftfulThinking/SwiftfulLogging

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

32 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸš€ Learn how to build and use this package: https://www.swiftful-thinking.com/offers/REyNLwwH

SwiftfulLogging

A reusable logger for Swift applications, built for Swift 6. LogManager coordinates multiple LogService implementations (Console, Firebase, Mixpanel, etc.) through a single API. Includes @Observable support.

Setup

Details (Click to expand)

Add SwiftfulLogging to your project.

https://github.com/SwiftfulThinking/SwiftfulLogging.git

Import the package.

import SwiftfulLogging

Create an instance of LogManager with one or more services:

// Development β€” console only
let logger = LogManager(services: [ConsoleService()])

// Production β€” multiple services
let logger = LogManager(services: [
    ConsoleService(),
    FirebaseAnalyticsService(),
    FirebaseCrashlyticsService(),
    MixpanelService(token: "your_token")
])

Optionally add to the SwiftUI environment:

Text("Hello, world!")
    .environment(logger)

Services

Details (Click to expand)

LogManager is initialized with an array of LogService. ConsoleService is included in the package. Other services are separate packages so you can pick and choose:

ConsoleService

// Default β€” prints parameters, uses stdout
let console = ConsoleService()

// Custom β€” hide parameters, use OSLog
let console = ConsoleService(printParameters: false, system: .osLog)

Custom LogService

Create your own by conforming to the protocol:

public protocol LogService: Sendable {
    func identifyUser(userId: String, name: String?, email: String?)
    func addUserProperties(dict: [String: Any], isHighPriority: Bool)
    func deleteUserProfile()
    func trackEvent(event: LoggableEvent)
    func trackScreenView(event: LoggableEvent)
}

Track Events

Details (Click to expand)

Log events with a name, optional parameters, and a log type:

logger.trackEvent(eventName: "ButtonTapped")
logger.trackEvent(eventName: "ButtonTapped", parameters: ["button_id": "save"])
logger.trackEvent(eventName: "ButtonTapped", parameters: ["button_id": "save"], type: .analytic)

Use AnyLoggableEvent for convenience:

let event = AnyLoggableEvent(eventName: "ButtonTapped", parameters: ["button_id": "save"], type: .analytic)
logger.trackEvent(event: event)

Recommended: Use the LoggableEvent protocol with custom enums for type-safe events:

enum Event: LoggableEvent {
    case screenDidAppear(title: String)
    case buttonTapped(id: String)
    case screenError(error: Error)

    var eventName: String {
        switch self {
        case .screenDidAppear:  return "ScreenAppear"
        case .buttonTapped:     return "ButtonTapped"
        case .screenError:      return "ScreenError"
        }
    }

    var parameters: [String: Any]? {
        switch self {
        case .screenDidAppear(let title):
            return ["title": title]
        case .buttonTapped(let id):
            return ["button_id": id]
        case .screenError(let error):
            return ["error_description": error.localizedDescription]
        }
    }

    var type: LogType {
        switch self {
        case .screenDidAppear, .buttonTapped:
            return .analytic
        case .screenError:
            return .severe
        }
    }
}
logger.trackEvent(event: Event.screenDidAppear(title: "Home"))

Log Types

Details (Click to expand)

Every event has a LogType that classifies its severity:

logger.trackEvent(eventName: "UserLoaded", type: .info)      // Informational, not an issue
logger.trackEvent(eventName: "ScreenAppear", type: .analytic) // Standard analytics (default)
logger.trackEvent(eventName: "RetryFailed", type: .warning)   // Non-breaking issue
logger.trackEvent(eventName: "CrashDetected", type: .severe)  // Breaks user experience
Type Purpose
.info Informational logging, not issues or errors
.analytic Standard analytics events (default)
.warning Issues that should not occur but don't break UX
.severe Critical errors that affect user experience

Services can use the log type to handle events differently. For example, FirebaseCrashlyticsService only records .severe events as errors.

Track Screen Views

Details (Click to expand)

Track screen views separately from events. Some analytics services (e.g. Firebase Analytics) have dedicated screen view tracking.

let event = AnyLoggableEvent(eventName: "HomeScreen", type: .analytic)
logger.trackScreenView(event: event)

// Or with a custom LoggableEvent enum
logger.trackScreenView(event: Event.screenDidAppear(title: "Home"))

Manage User Profile

Details (Click to expand)

Identify the current user (log them in to all services):

logger.identifyUser(userId: "abc123", name: "Nick", email: "hello@swiftful-thinking.com")

Add user properties for analytics segmentation:

logger.addUserProperties(dict: ["is_premium": true, "plan": "annual"])
logger.addUserProperties(dict: ["account_type": "pro"], isHighPriority: true)

Note: isHighPriority matters for services with limited user property slots (e.g. Firebase Analytics only sets properties when isHighPriority is true).

Delete user profile:

logger.deleteUserProfile()

Claude Code

This package includes a .claude/swiftful-logging-rules.md with usage guidelines, event patterns, and integration advice for projects using Claude Code.

Platform Support

  • iOS 17.0+
  • macOS 14.0+

License

SwiftfulLogging is available under the MIT license.

About

Logger for Swift 6 w/ Observable support

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages