Skip to content

Repository files navigation

A lightweight logging framework written in Swift

log

LicenseSwift CompatibilityPlatform CompatibilityCICodeCovGitHub release; latest by dateGitHub commit activity

Description

Log is a lightweight, flexible Swift logging framework that provides elegant and customizable logging capabilities for iOS, macOS, tvOS, watchOS, and visionOS applications. With support for multiple output destinations and custom formatting, Log makes debugging and monitoring your apps easier than ever.

Features

Multiple Output Destinations - Console, system log (os_log), and custom printers
🎨 Customizable Formatting - Prefix, timestamp, and custom formatters
📊 Log Levels - Fine-grained control over message severity
🔧 Extensible - Easy to create custom printers and formatters
📱 Cross-Platform - Works on iOS, macOS, tvOS, watchOS, and visionOS
Lightweight - Minimal footprint with zero dependencies
🎯 Type-Safe - Leverages Swift's type system for compile-time safety

Table of Contents

Requirements

PlatformMinimum Version
iOS13.0+
macOS10.15+
tvOS13.0+
watchOS7.0+
visionOS1.0+
Xcode15.3+
Swift5.10+

Installation

Swift Package Manager

Add the following dependency to your Package.swift:

dependencies:[.package(url:"https://github.com/space-code/log.git", from:"1.3.0")]

Or add it through Xcode:

  1. File > Add Package Dependencies
  2. Enter package URL: https://github.com/space-code/log.git
  3. Select version requirements

Quick Start

import Log
// Create printers
letconsolePrinter=ConsolePrinter()letosPrinter=OSPrinter()
// Create logger
letlog=Logger(
printers:[consolePrinter, osPrinter],
logLevel:.all
)
// Start logging
log.info(message:"Application started")
log.debug(message:"Debug information")
log.error(message:"Something went wrong")

Usage

Creating a Logger

Log provides two main printer implementations out of the box:

import Log
// Console printer for Xcode console output
letconsolePrinter=ConsolePrinter()
// OS printer for system console (Console.app)
letosPrinter=OSPrinter()
// Create logger with multiple printers
letlog=Logger(
printers:[consolePrinter, osPrinter],
logLevel:.all
)

Log Levels

Log supports various severity levels for organizing your messages:

import Log
letlog=Logger(printers:[ConsolePrinter()], logLevel:.all)
// Different log levels
log.debug(message:"Debug information")
log.info(message:"General informational messages")
log.error(message:"Error messages")
log.fault(message:"Critical fault messages")

Available Log Levels:

  • .debug - Debug information
  • .info - General informational messages
  • .error - Error messages
  • .fault - Critical system faults
  • .all - Log all messages

Filtering by Level:

// Only log errors
letlog=Logger(
printers:[ConsolePrinter()],
logLevel:.errors
)
log.debug(message:"This won't be printed")
log.error(message:"This will be printed")

Printers

Printers determine where your log messages are output:

ConsolePrinter - Outputs to Xcode console:

letconsolePrinter=ConsolePrinter(
formatters:[PrefixLogFormatter(name:"MyApp"),TimestampLogFormatter(dateFormat:"HH:mm:ss")])

OSPrinter - Outputs to system log (viewable in Console.app):

letosPrinter=OSPrinter(
formatters:[PrefixLogFormatter(name:"MyApp")])

Using Multiple Printers:

// Log to both Xcode console and system log
letlog=Logger(
printers:[ConsolePrinter(formatters:[TimestampLogFormatter()]),OSPrinter(formatters:[PrefixLogFormatter(name:"MyApp")])],
logLevel:.all
)

Message Formatting

Formatters transform your log messages before they're printed. Log includes two built-in formatters:

FormatterDescription
PrefixLogFormatterAdds a specified prefix to messages
TimestampLogFormatterAdds a timestamp based on date format

Using Formatters:

import Log
// Prefix formatter
letprefixFormatter=PrefixLogFormatter(name:"NetworkLayer")letprinter=ConsolePrinter(formatters:[prefixFormatter])letlog=Logger(printers:[printer], logLevel:.all)
log.info(message:"Request started")
// Output: ℹ️ [NetworkLayer] => Request started
// Timestamp formatter
lettimestampFormatter=TimestampLogFormatter(dateFormat:"yyyy-MM-dd HH:mm:ss")letprinter2=ConsolePrinter(formatters:[timestampFormatter])letlog2=Logger(printers:[printer2], logLevel:.all)
log2.info(message:"User logged in")
// Output: ℹ️ 2025-12-22 15:56:42 User logged in
// Combining formatters
letcombinedPrinter=ConsolePrinter(formatters:[TimestampLogFormatter(dateFormat:"HH:mm:ss"),PrefixLogFormatter(name:"API")])letlog3=Logger(printers:[combinedPrinter], logLevel:.all)
log3.error(message:"Connection failed")
// Output: ⚠️ [API] => 15:56:42 Connection failed

Custom Formatters

Create custom formatters by conforming to the ILogFormatter protocol:

import Log
structEnvironmentFormatter:ILogFormatter{letenvironment:Stringfunc format(message:String, with logLevel:LogLevel)->String{return"[\(environment.uppercased())] \(message)"}}
// Usage
letformatter=EnvironmentFormatter(environment:"production")letprinter=ConsolePrinter(formatters:[formatter])letlog=Logger(printers:[printer], logLevel:.all)
log.info(message:"Server started")
// Output: [PRODUCTION] Server started

Advanced Custom Formatter:

structContextualFormatter:ILogFormatter{letincludeThread:BoolletincludeFile:Boolfunc format(message:String, with logLevel:LogLevel)->String{varcomponents:[String]=[]if includeThread {
components.append("[Thread: \(Thread.current.threadName)]")}if includeFile {
components.append("[File: \(#file)]")}
components.append(message)return components.joined(separator:"")}}

Custom Printer:

import Log
finalclassFilePrinter:IPrinter{letformatters:[ILogFormatter]letfileURL:URLinit(formatters:[ILogFormatter]=[], fileURL:URL){self.formatters = formatters
self.fileURL = fileURL
}func log(_ message:String, logLevel:Log.LogLevel){varformattedMessage= message
forformatterin formatters {
formattedMessage = formatter.format(
message: formattedMessage,
with: logLevel
)}iflet data =(formattedMessage +"\n").data(using:.utf8){
// Write to file
}}}

Common Use Cases

Application Logging

import Log
classAppDelegate:UIResponder,UIApplicationDelegate{privateletlog=Logger(
printers:[ConsolePrinter(formatters:[TimestampLogFormatter(dateFormat:"HH:mm:ss.SSS"),PrefixLogFormatter(name:"MyApp")]),OSPrinter(formatters:[PrefixLogFormatter(name:"MyApp")])],
logLevel:.all
)func application(
_ application:UIApplication,
didFinishLaunchingWithOptions launchOptions:[UIApplication.LaunchOptionsKey:Any]?)->Bool{
log.info(message:"Application launched")setupApplication()returntrue}privatefunc setupApplication(){
log.debug(message:"Configuring application")
// Configuration code
log.info(message:"Application configured successfully")}}

Network Layer Logging

import Log
classNetworkManager{privateletlog=Logger(
printers:[ConsolePrinter(formatters:[TimestampLogFormatter(),PrefixLogFormatter(name:"Network")])],
logLevel:.debug
)func fetchData(from url:URL)asyncthrows->Data{
log.debug(message:"Requesting: \(url.absoluteString)")do{let(data, response)=tryawaitURLSession.shared.data(from: url)iflet httpResponse = response as?HTTPURLResponse{
log.info(message:"Response: \(httpResponse.statusCode)")}return data
}catch{
log.error(message:"Request failed: \(error.localizedDescription)")throw error
}}}

Database Operations

import Log
classDatabaseManager{privateletlog=Logger(
printers:[ConsolePrinter(formatters:[PrefixLogFormatter(name:"Database")])],
logLevel:.all
)func saveRecord(_ record:Record)throws{
log.debug(message:"Attempting to save record: \(record.id)")do{try database.insert(record)
log.info(message:"Record saved successfully: \(record.id)")}catch{
log.error(message:"Failed to save record: \(error)")throw error
}}func deleteRecord(id:String)throws{
log.info(message:"Deleting record: \(id)")try database.delete(id)
log.info(message:"Record deleted: \(id)")}}

Debug vs Production Logging

import Log
classLoggerFactory{staticfunc createLogger()->Logger{#if DEBUGreturnLogger(
printers:[ConsolePrinter(formatters:[TimestampLogFormatter(dateFormat:"HH:mm:ss.SSS"),PrefixLogFormatter(name:"Debug")])],
logLevel:.all
)#elsereturnLogger(
printers:[OSPrinter(formatters:[PrefixLogFormatter(name:"Production")])],
logLevel:.error // Only log errors in production
)#endif}}
// Usage
letlog=LoggerFactory.createLogger()

Communication

Contributing

We love contributions! Please feel free to help out with this project. If you see something that could be made better or want a new feature, open up an issue or send a Pull Request.

Development Setup

Bootstrap the development environment:

make bootstrap

For detailed contribution guidelines, see CONTRIBUTING.md.

Author

Nikita Vasilev

License

Log is released under the MIT license. See LICENSE for details.


⬆ back to top

Made with ❤️ by space-code

About

Log is a lightweight, flexible Swift logging framework that provides elegant and customizable logging capabilities for iOS, macOS, tvOS, watchOS, and visionOS applications.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages