Skip to content

Commit

Permalink
Merge pull request #109 from GetToSet/ethanwong/unified-logging
Browse files Browse the repository at this point in the history
Support for Apple’s unified logging system.
  • Loading branch information
dyerc authored Aug 22, 2022
2 parents fbfb0cc + cc03091 commit 58eea28
Show file tree
Hide file tree
Showing 13 changed files with 101 additions and 41 deletions.
14 changes: 7 additions & 7 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ custom_rules:
regex: "@objcMembers"
message: "Explicitly use @objc on each member you want to expose to Objective-C"
severity: error
# no_direct_standard_out_logs:
# name: "Writing log messages directly to standard out is disallowed"
# regex: "(\\bprint|\\bdebugPrint|\\bdump|Swift\\.print|Swift\\.debugPrint|Swift\\.dump)\\s*\\("
# match_kinds:
# - identifier
# message: "Don't commit `print(…)`, `debugPrint(…)`, or `dump(…)` as they write to standard out in release. Either log to a dedicated logging system or silence this warning in debug-only scenarios explicitly using `// swiftlint:disable:next no_direct_standard_out_logs`"
# severity: warning
no_direct_standard_out_logs:
name: "Writing log messages directly to standard out is disallowed"
regex: "(\\bprint|\\bdebugPrint|\\bdump|Swift\\.print|Swift\\.debugPrint|Swift\\.dump)\\s*\\("
match_kinds:
- identifier
message: "Don't commit `print(…)`, `debugPrint(…)`, or `dump(…)` as they write to standard out in release. Either log to a dedicated logging system or silence this warning in debug-only scenarios explicitly using `// swiftlint:disable:next no_direct_standard_out_logs`"
severity: warning
12 changes: 12 additions & 0 deletions Doughnut.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
6B816BE927E71A1A00EED863 /* ModelTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B816BE827E71A1A00EED863 /* ModelTestCase.swift */; };
6B816BEB27E71A2700EED863 /* DoughnutTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B816BEA27E71A2700EED863 /* DoughnutTestCase.swift */; };
6B816BED27E71A6700EED863 /* PodcastModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B816BEC27E71A6700EED863 /* PodcastModelTests.swift */; };
6B8745502842015000AB07CF /* OSLog+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B87454F2842015000AB07CF /* OSLog+Extensions.swift */; };
6B94DF4C278968F500BCB149 /* NSTableView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B94DF4B278968F500BCB149 /* NSTableView+Extensions.swift */; };
6B96F45D27CE6F10001941BA /* PodcastSearchField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B96F45C27CE6F10001941BA /* PodcastSearchField.swift */; };
6B9C30BB27B5708300D462BE /* BaseTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B9C30BA27B5708300D462BE /* BaseTableView.swift */; };
Expand Down Expand Up @@ -129,6 +130,7 @@
6B816BE827E71A1A00EED863 /* ModelTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelTestCase.swift; sourceTree = "<group>"; };
6B816BEA27E71A2700EED863 /* DoughnutTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoughnutTestCase.swift; sourceTree = "<group>"; };
6B816BEC27E71A6700EED863 /* PodcastModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PodcastModelTests.swift; sourceTree = "<group>"; };
6B87454F2842015000AB07CF /* OSLog+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OSLog+Extensions.swift"; sourceTree = "<group>"; };
6B94DF4B278968F500BCB149 /* NSTableView+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTableView+Extensions.swift"; sourceTree = "<group>"; };
6B96F45C27CE6F10001941BA /* PodcastSearchField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PodcastSearchField.swift; sourceTree = "<group>"; };
6B9C30BA27B5708300D462BE /* BaseTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTableView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -258,6 +260,7 @@
children = (
6B0605C32788626F00A8A91E /* AppKit */,
6BC6396227A68E0C00535897 /* CoreMedia */,
6B209FD8284331BC006F3C23 /* OSLog */,
);
name = Extensions;
sourceTree = "<group>";
Expand All @@ -275,6 +278,14 @@
name = AppKit;
sourceTree = "<group>";
};
6B209FD8284331BC006F3C23 /* OSLog */ = {
isa = PBXGroup;
children = (
6B87454F2842015000AB07CF /* OSLog+Extensions.swift */,
);
name = OSLog;
sourceTree = "<group>";
};
6B571B4627E74C31008E1534 /* Fixtures */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -896,6 +907,7 @@
837D52BE1F8E622200C17514 /* TasksViewController.swift in Sources */,
8379899B1F81616C00234577 /* SeekSlider.swift in Sources */,
6B36624627CFB339008E1CA5 /* NSImage+Extensions.swift in Sources */,
6B8745502842015000AB07CF /* OSLog+Extensions.swift in Sources */,
837068131F7BBD63007FE973 /* EpisodeCellView.swift in Sources */,
83667DF41F76D22600F1ABC0 /* DetailViewController.swift in Sources */,
6BC6396427A68E2100535897 /* CMTime+Extensions.swift in Sources */,
Expand Down
12 changes: 7 additions & 5 deletions Doughnut/CrashReport/CrashReporter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

import Foundation
import OSLog

import CrashReporter

Expand All @@ -27,21 +28,22 @@ final class CrashReporter {
}

private static var sharedInstance = CrashReporter()
private static let log = OSLog.main(category: "CrashReporter")

private var plCrashReporter: PLCrashReporter?

private init() {
let config = PLCrashReporterConfig(signalHandlerType: .BSD, symbolicationStrategy: .symbolTable)
guard let plCrashReporter = PLCrashReporter(configuration: config) else {
print("CrashReporter: could not create an instance of PLCrashReporter")
Self.log(level: .error, "could not create an instance of PLCrashReporter")
return
}
self.plCrashReporter = plCrashReporter
// enable the PLCrashReporter
do {
try plCrashReporter.enableAndReturnError()
} catch {
print("CrashReporter: failed to enable PLCrashReporter: \(error)")
Self.log(level: .error, "failed to enable PLCrashReporter: \(error)")
}
}

Expand All @@ -67,17 +69,17 @@ final class CrashReporter {
if let text = PLCrashReportTextFormatter.stringValue(for: report, with: PLCrashReportTextFormatiOS) {
return text
} else {
print("CrashReporter: can't convert the report to text")
Self.log(level: .error, "can't convert the report to text")
}
} catch {
print("CrashReporter failed to load and parse crash report: \(error)")
Self.log(level: .error, "failed to load and parse crash report: \(error)")
}

return nil
}

func forceCrash() {
fatalError("Force crashd in \(#function)")
fatalError("Force crash in \(#function)")
}

}
6 changes: 3 additions & 3 deletions Doughnut/Library/Episode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ class Episode: Record {
if let url = url() {
NSWorkspace.shared.recycle([url], completionHandler: { _, error in
if let error = error {
print("Failed to move to trash \(error)")
Library.log(level: .error, "Failed to move to trash \(error)")
} else {
if let completion = completion {
completion(url)
Expand Down Expand Up @@ -228,7 +228,7 @@ class Episode: Record {
if copyToLibrary {
// Perform the copy
guard let storagePath = podcast.storagePath() else {
print("Could not determine podcast storage location")
Library.log(level: .error, "Could not determine podcast storage location")
return
}

Expand All @@ -245,7 +245,7 @@ class Episode: Record {

episode.fileName = fileName
} catch {
print("Failed to copy \(url.path) to library. Output destination \(outputPath)")
Library.log(level: .error, "Failed to copy \(url.path) to library. Output destination \(outputPath)")
return
}
} else {
Expand Down
18 changes: 12 additions & 6 deletions Doughnut/Library/Library.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

import Foundation
import OSLog

import FeedKit
import GRDB
Expand Down Expand Up @@ -45,6 +46,8 @@ class Library: NSObject {
static var global = Library()
static let databaseFilename = "Doughnut Library.dnl"

static let log = OSLog.main(category: "Library")

enum Events: String {
case Subscribed
case Unsubscribed
Expand Down Expand Up @@ -94,7 +97,10 @@ class Library: NSObject {
var configuration = Configuration()
if Preference.bool(for: Preference.Key.debugSQLTraceEnabled) {
configuration.prepareDatabase { db in
db.trace { print($0) }
db.trace {
// swiftlint:disable:next no_direct_standard_out_logs
print($0)
}
}
}
dbQueue = try DatabaseQueue(path: databaseFile().path, configuration: configuration)
Expand All @@ -103,7 +109,7 @@ class Library: NSObject {
try LibraryMigrations.migrate(db: dbQueue)

if !Preference.testEnv() {
print("Connected to Doughnut library at \(path.path)")
Self.log(level: .info, "Connected to Doughnut library at \(path.path)")
}

try dbQueue.inDatabase({ db in
Expand All @@ -113,7 +119,7 @@ class Library: NSObject {
podcast.loadEpisodes(db: db)

#if DEBUG
print("Loading \(podcast.title) with \(podcast.episodes.count) episodes")
Self.log(level: .debug, "Loading \(podcast.title) with \(podcast.episodes.count) episodes")
#endif
}

Expand Down Expand Up @@ -188,7 +194,7 @@ class Library: NSObject {
}

static func handleDatabaseError(_ error: Error) {
print("Library: error \(error), stack trace: \(Thread.callStackSymbols)")
Self.log(level: .error, "Library: error \(error), stack trace: \(Thread.callStackSymbols)")
}

static func sanitizePath(_ path: String) -> String {
Expand Down Expand Up @@ -303,13 +309,13 @@ class Library: NSObject {
if let storagePath = podcast.storagePath() {
NSWorkspace.shared.recycle([storagePath], completionHandler: { (trashedFiles, error) in
if let error = error {
print("Failed to move podcast data to trash: \(error.localizedDescription)")
Self.log(level: .error, "Failed to move podcast data to trash: \(error.localizedDescription)")

let alert = NSAlert()
alert.messageText = "Failed to trash data"
alert.informativeText = error.localizedDescription
} else {
print("Moved podcast data stored at \(trashedFiles) to trash")
Self.log(level: .info, "Moved podcast data stored at \(trashedFiles) to trash")
}
})
}
Expand Down
4 changes: 2 additions & 2 deletions Doughnut/Library/Podcast.swift
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class Podcast: Record {
do {
try FileManager.default.createDirectory(at: pathUrl, withIntermediateDirectories: true, attributes: nil)
} catch {
print("Failed to create directory \(error)")
Library.log(level: .error, "Failed to create directory \(error)")
}
}

Expand Down Expand Up @@ -295,7 +295,7 @@ class Podcast: Record {
guard let rssFeed = feed.rssFeed else { return [] }
return self.parse(feed: rssFeed)
case .failure(let error):
print("Error reloading \(self.title): \(String(describing: error.localizedDescription))")
Library.log(level: .error, "Error reloading \(self.title): \(String(describing: error.localizedDescription))")
return []
}
}
Expand Down
2 changes: 1 addition & 1 deletion Doughnut/Library/Utils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class Utils {
}
}
} catch let error {
print(error)
Library.log(level: .error, "Failed to parse iTunes feed with: \(error)")
}

completion(nil)
Expand Down
6 changes: 2 additions & 4 deletions Doughnut/Player/Player+NowPlayingInfoCenter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ extension Player {
}

func updateNowPlayingEpisodeInfo() {
// TODO: convert print statemenets to logs with levels.
print("[NowPlayingInfo]: updateNowPlayingEpisodeInfo")
Self.log(level: .debug, "[NowPlayingInfo]: updateNowPlayingEpisodeInfo called")

guard let currentEpisode = currentEpisode else {
nowPlayingEpisodeInfoDictionary = [:]
Expand Down Expand Up @@ -68,8 +67,7 @@ extension Player {
}

func updateNowPlayingPlaybackInfo() {
// TODO: convert print statemenets to logs with levels.
// print("[NowPlayingInfo]: updateNowPlayingPlaybackInfo")
// Self.logger.debug("[NowPlayingInfo]: updateNowPlayingPlaybackInfo called")

// TODO: Limit the rate of sending the following values.
let nowPlayingInfoDictionary = nowPlayingEpisodeInfoDictionary.merging([
Expand Down
14 changes: 7 additions & 7 deletions Doughnut/Player/Player+RemoteCommandCenter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,25 @@ extension Player {
// Playback Commands

remoteCommandCenter.pauseCommand.addTarget { [weak self] _ in
print("[RemoteCommand]: Receive pauseCommand")
Self.log(level: .debug, "[RemoteCommand]: Receive pauseCommand")
self?.pause()
return .success
}

remoteCommandCenter.playCommand.addTarget { [weak self] _ in
print("[RemoteCommand]: Receive playCommand")
Self.log(level: .debug, "[RemoteCommand]: Receive playCommand")
self?.play()
return .success
}

remoteCommandCenter.stopCommand.addTarget { [weak self] _ in
print("[RemoteCommand]: Receive stopCommand")
Self.log(level: .debug, "[RemoteCommand]: Receive stopCommand")
self?.stop()
return .success
}

remoteCommandCenter.togglePlayPauseCommand.addTarget { [weak self] _ in
print("[RemoteCommand]: Receive togglePlayPauseCommand")
Self.log(level: .debug, "[RemoteCommand]: Receive togglePlayPauseCommand")
self?.togglePlay()
return .success
}
Expand All @@ -66,14 +66,14 @@ extension Player {
// Skip Interval Commands

remoteCommandCenter.skipForwardCommand.addTarget { [weak self] event in
print("[RemoteCommand]: Receive skipForwardCommand")
Self.log(level: .debug, "[RemoteCommand]: Receive skipForwardCommand")
guard let event = event as? MPSkipIntervalCommandEvent else { return .commandFailed }
self?.skipAhead(seconds: event.interval)
return .success
}

remoteCommandCenter.skipBackwardCommand.addTarget { [weak self] event in
print("[RemoteCommand]: Receive skipBackwardCommand")
Self.log(level: .debug, "[RemoteCommand]: Receive skipBackwardCommand")
guard let event = event as? MPSkipIntervalCommandEvent else { return .commandFailed }
self?.skipBack(seconds: event.interval)
return .success
Expand All @@ -86,7 +86,7 @@ extension Player {
remoteCommandCenter.seekBackwardCommand.isEnabled = false

remoteCommandCenter.changePlaybackPositionCommand.addTarget { [weak self] event in
print("[RemoteCommand]: Receive changePlaybackPositionCommand")
Self.log(level: .debug, "[RemoteCommand]: Receive changePlaybackPositionCommand")
guard let event = event as? MPChangePlaybackPositionCommandEvent else { return .commandFailed }
self?.seek(seconds: event.positionTime)
return .success
Expand Down
14 changes: 9 additions & 5 deletions Doughnut/Player/Player.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import AVFoundation
import Cocoa
import OSLog

protocol PlayerDelegate: AnyObject {
func update(forEpisode episode: Episode?)
Expand All @@ -33,6 +34,8 @@ enum PlayerLoadStatus {
final class Player: NSObject {
static var global = Player()

static let log = OSLog.main(category: "Player")

weak var delegate: PlayerDelegate?

private static let playedThreshold: Double = 0.9
Expand Down Expand Up @@ -131,7 +134,7 @@ final class Player: NSObject {
assert(false, "'.loading' should not be returned in the completionHandler of loadValuesAsynchronously(forKeys:).")
break
default:
print("Failed to load the AVAsset failed with status: \(status), error: \(error?.localizedDescription ?? "nil").")
Player.log(level: .error, "Failed to load the AVAsset failed with status: \(status), error: \(error?.localizedDescription ?? "nil")")
break
}
cleanupLoadStatusOnFail()
Expand Down Expand Up @@ -251,7 +254,7 @@ final class Player: NSObject {
loadStatus = .none
}

print("Playing")
Self.log(level: .debug, "Playing")
postPlaybackStatusUpdates()
}
}
Expand Down Expand Up @@ -340,9 +343,9 @@ final class Player: NSObject {
if #available(macOS 11.0, *) {
AVAudioRoutingArbiter.shared.begin(category: .playback) { defaultDeviceChanged, error in
if let error = error {
print("begins routing arbitration failed, defaultDeviceChanged: \(defaultDeviceChanged), error: \(error)")
Self.log(level: .error, "begins routing arbitration failed, defaultDeviceChanged: \(defaultDeviceChanged), error: \(error)")
} else {
print("begins routing arbitration, defaultDeviceChanged: \(defaultDeviceChanged)")
Self.log(level: .debug, "begins routing arbitration, defaultDeviceChanged: \(defaultDeviceChanged)")
}
}
}
Expand All @@ -351,7 +354,7 @@ final class Player: NSObject {
private func leaveRoutingArbitration() {
if #available(macOS 11.0, *) {
AVAudioRoutingArbiter.shared.leave()
print("leaves routing arbitration")
Self.log(level: .debug, "leaves routing arbitration")
}
}

Expand Down Expand Up @@ -409,6 +412,7 @@ final class Player: NSObject {

// If there are channels, it's an input device

// swiftlint:disable:next no_direct_standard_out_logs
Swift.print("Found output device '\(name)' with \(channelCount) channels [\(id)]")
inputDevices.append(id)
}
Expand Down
2 changes: 1 addition & 1 deletion Doughnut/Preference/Preference.swift
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ class Preference {
do {
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil)
} catch {
print("Failed to create directory \(error)")
Library.log(level: .error, "Failed to create directory \(error)")
}
}
}
Expand Down
Loading

0 comments on commit 58eea28

Please sign in to comment.