Skip to content

PerseusRealDeal/ConsolePerseusLogger

Repository files navigation

ConsolePerseusLogger — Xcode 14.2+

iOS approbation app macOS approbation app

Light-weight logging lover in Swift. Hereinafter CPL stands for Console Perseus Logger.

  • Log to the console.
  • Log to macOS Console.app.
  • Log to custom output.

[TYPE] [DATE] [TIME] [PID:TID] message, file: #, line: #

CPL is a single author and personale solution developed in person-to-person relationship paradigm.

Actions Status Style Version Platforms Xcode 14.2 Swift 5.7 License

Integration Capabilities

Standalone Swift Package Manager compatible

Tip

To adopt CPL for the specifics you need use Standalone.

Approbation Matrix

A3 Environment and Approbation / CHANGELOG for details.

Xcode playground download page.

In brief > Idea to use

USE LOGGER LIKE A VARIABLE ANYWHERE YOU WANT.

Image

Build requirements

Tip

As the single source code CPLStar.swift CPL with minimum changes can be used even in Xcode 10.1, just remove all statements starting with if #available(iOS 14.0, macOS 11.0, *).

Third-party software

Type Name License
Style SwiftLint / v0.57.0 for Monterey+ MIT
Script SwiftLint Shell Script to run SwiftLint MIT
Action mxcl/xcodebuild@v3 Unlicense
Action cirruslabs/swiftlint-action@v1 MIT

Installation

Standalone: the single source code file CPLStar.swift

Swift Package Manager: https://github.com/perseusrealdeal/ConsolePerseusLogger

Note

If output is consoleapp and Environment Variable OS_ACTIVITY_MODE in disable log messaging will be restricted for Xcode console, but only.

Image

Usage

Log to the console

import ConsolePerseusLogger

log.message("[\(type(of: self))].\(#function)")

Image

Log to macOS Console.app

import ConsolePerseusLogger

// MARK: - Log to Console.app

// log.logObject = ("MyApp", "MyLover") // Customs for Console.app Subsystem and Category.

log.output = .consoleapp
log.message("The app's start point...", .info)

Image

Custom log

import ConsolePerseusLogger

typealias Level = ConsolePerseusLogger.PerseusLogger.Level

func customPrint(_ text: String, _ type: Level, _ localTime: LocalTime, _ owner: PIDandTID) {

    let time = "[\(localTime.date)] [\(localTime.time)]"
    let id = "[\(owner.pid):\(owner.tid)]"

    print("[MYLOG] [\(type)] \(time) \(id) \(text)")
}

log.customActionOnMessage = customPrint(_:_:_:_:)

log.format = .textonly
log.output = .custom

log.message("The app's start point...", .info)

Image

Debugging SwiftUI

Case 1: as is

Image(systemName: "globe")
    .onAppear {
        log.message("This is the debug output.")
    }

Case 2: wrapper

Add an extension on View that returns itself and calls the logger's message method:

extension View {
    func message(_ text: @autoclosure () -> String,
                 _ type: PerseusLogger.Level = .debug,
                 _ oput: PerseusLogger.Output = PerseusLogger.output,
                 _ file: StaticString = #file,
                 _ line: UInt = #line) -> Self {

        log.message(text(), type, oput, file, line)

        return self
    }
}

Then use message as a view modifier to print debug information to the console when the view is built:

VStack {
   ForEach(colors, id: \.self) { color in
      Circle()
         .foregroundColor(color)
         .message("\(color)")
   }
}

Image

Log level and message types

CPL applies the most common log types for indicating information category.

Level Message Type Description
5 DEBUG Debugging only
4 INFO Helpful, but not essential
3 NOTICE Might result in a failure
2 ERROR Errors seen during the code execution
1 FAULT Faults and bugs in the code

Also, CPL considers Message Type to filter, look how it works:

Image

Setting the Logger Up

Default values of CPL options depend on DEBUG/RELEASE.

Option Default in DEBUG Default in RELEASE
tuned .on .off
output .standard .consoleapp
level .debug .notice

Other CPL options are the same for DEBUG/RELEASE by default.

Option Default in DEBUG Default in RELEASE
subsecond .nanosecond .nanosecond
tidnumber .hexadecimal .hexadecimal
format .short .short
marks true true
time false false
owner false false
directives false false
logObject ("Perseus", "Lover") ("Perseus", "Lover")

Special option goes kinda lifehack. Matter only if Simulator.

Option Default in DEBUG Default in RELEASE
debugIsInfo true true

Load (reset) CPL options with JSON config

Each option can be reseted in run time with json config except option turned.

Case 1: Using predefined json profile

import ConsolePerseusLogger

let isReseted = log.loadConfig(.debugRoutine)
let result = isReseted ? "CPL current options loaded." : "Failed to load options!"

log.message(result)

Case 2: Using custom profile (URL required)

import ConsolePerseusLogger

var result = ""

if let path = Bundle.main.url(forResource: "CPLConfig", withExtension: "json") {
    let isLoaded = log.loadConfig(path)
    result = isLoaded ? "Options successfully loaded." : "Failed to load options!"
} else {
    result = "Failed to create URL!"
}

log.message(result)

Image

CPL in SPM package

In case if CPL in use as a standalone file in SPM package.

//
//  main.swift
//

import ConsolePerseusLogger

import class PackageA.PerseusLogger
import class PackageB.PerseusLogger

typealias logA = PackageA.PerseusLogger
typealias logB = PackageB.PerseusLogger

// MARK: - Subloggers

logA.turned = .off
logB.turned = .off

// MARK: - Logger

log.message("The app's start point...", .info)

Console.app and Simulator

Just a matter of fact that Console.app doesn't show any DEBUG message from any app running on Simulator (even if "Include Debug Messages" tapped in Console.app).

Console Perseus Logger running on Simulator doesn't pass DEBUG message to Console.app, instead it passes INFO message with text of DEBUG message by default if Simulator runs, so, a passed message being INFO looks like a DEBUG and it works perfactly well.

If for some reasons CPL must pass DEBUG like a DEBUG message the option should take false log.debugIsInfo = false.

#if targetEnvironment(simulator)
    log.debugIsInfo = false
#endif

Points taken into account

License MIT

Copyright © 7531 - 7533 Mikhail A. Zhigulin of Novosibirsk
Copyright © 7531 - 7533 PerseusRealDeal

  • The year starts from the creation of the world according to a Slavic calendar.
  • September, the 1st of Slavic year. It means that "Sep 01, 2024" is the beginning of 7533.

Other Required License Notices

© 2025 The SwiftLint Contributors for SwiftLint
© GitHub for GitHub Action cirruslabs/swiftlint-action@v1
© 2021 Alexandre Colucci, geteimy.com for Shell Script SucceedsPostAction.sh

LICENSE for details.

Credits

Balance and Control kept by Mikhail A. Zhigulin
Source Code written by Mikhail A. Zhigulin
Documentation prepared by Mikhail A. Zhigulin
Product Approbation tested by Mikhail A. Zhigulin

Author

© Mikhail A. Zhigulin of Novosibirsk.