Skip to content

Commit

Permalink
✨ User structured logging with OSLog
Browse files Browse the repository at this point in the history
  • Loading branch information
igorkulman committed Jan 25, 2024
1 parent 80d836f commit 48bc8a0
Show file tree
Hide file tree
Showing 13 changed files with 40 additions and 82 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Sample iOS app written the way I write iOS apps because I cannot share the app I
* Adding custom reactive properties
* Basic Dark mode support
* Custom operator for simple UI code
* Generated code to safely access assets
* Structured logging
* Xcode build plugins

## Getting started
Expand Down
14 changes: 5 additions & 9 deletions Sources/iOSSampleApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
F33474F4244F64D80034B1C2 /* Reusable in Frameworks */ = {isa = PBXBuildFile; productRef = F33474F3244F64D80034B1C2 /* Reusable */; };
F33474F7244F65050034B1C2 /* FeedKit in Frameworks */ = {isa = PBXBuildFile; productRef = F33474F6244F65050034B1C2 /* FeedKit */; };
F33474FA244F67270034B1C2 /* RxSwiftExt in Frameworks */ = {isa = PBXBuildFile; productRef = F33474F9244F67270034B1C2 /* RxSwiftExt */; };
F33A1F4124C9866F008ED2BD /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = F33A1F4024C9866F008ED2BD /* Log.swift */; };
F33A1F4124C9866F008ED2BD /* Logger+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F33A1F4024C9866F008ED2BD /* Logger+Extensions.swift */; };
F33EB3FE1FBDD81F0050560D /* UIViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F33EB3FD1FBDD81F0050560D /* UIViewController+Extensions.swift */; };
F35BD6392065111F000AE4E8 /* AppUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F35BD6382065111F000AE4E8 /* AppUITests.swift */; };
F3651D22203C1B0D0082A73A /* DataService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3651D21203C1B0D0082A73A /* DataService.swift */; };
Expand Down Expand Up @@ -82,7 +82,6 @@
F3C8DB41214EA7F200C1A654 /* FeedViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3C8DB40214EA7F200C1A654 /* FeedViewModelTests.swift */; };
F3CBB19621CCFFA00023EE18 /* RxSwift+WKWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3CBB19521CCFFA00023EE18 /* RxSwift+WKWebView.swift */; };
F3D6865C1F9B761E00879154 /* TestExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D6865B1F9B761E00879154 /* TestExtensions.swift */; };
F3D7D14B2441C599001695B9 /* DebugUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D7D14A2441C599001695B9 /* DebugUtils.swift */; };
F3EEA696234A3BE800A2FCB5 /* SnapshotHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EEA695234A3BE800A2FCB5 /* SnapshotHelper.swift */; };
/* End PBXBuildFile section */

Expand All @@ -109,7 +108,7 @@
F3208A7E1F84E48100B57B0E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F3208A881F84E83900B57B0E /* DataServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataServiceTests.swift; sourceTree = "<group>"; };
F3208A911F84EAF400B57B0E /* CustomSourceViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomSourceViewModelTests.swift; sourceTree = "<group>"; };
F33A1F4024C9866F008ED2BD /* Log.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Log.swift; sourceTree = "<group>"; };
F33A1F4024C9866F008ED2BD /* Logger+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Logger+Extensions.swift"; sourceTree = "<group>"; };
F33EB3FD1FBDD81F0050560D /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extensions.swift"; sourceTree = "<group>"; };
F35BD6362065111F000AE4E8 /* iOSSampleAppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = iOSSampleAppUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
F35BD6382065111F000AE4E8 /* AppUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppUITests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -172,7 +171,6 @@
F3C8DB40214EA7F200C1A654 /* FeedViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedViewModelTests.swift; sourceTree = "<group>"; };
F3CBB19521CCFFA00023EE18 /* RxSwift+WKWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RxSwift+WKWebView.swift"; sourceTree = "<group>"; };
F3D6865B1F9B761E00879154 /* TestExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestExtensions.swift; sourceTree = "<group>"; };
F3D7D14A2441C599001695B9 /* DebugUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugUtils.swift; sourceTree = "<group>"; };
F3EEA695234A3BE800A2FCB5 /* SnapshotHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SnapshotHelper.swift; path = ../../fastlane/SnapshotHelper.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -512,8 +510,6 @@
F3A812DD1F83761E00A09AAB /* Extensions */,
F3A812D61F83758000A09AAB /* Coordinators */,
F3A812D41F83754100A09AAB /* AppDelegate+Setup.swift */,
F3D7D14A2441C599001695B9 /* DebugUtils.swift */,
F33A1F4024C9866F008ED2BD /* Log.swift */,
F3C5F3512961BB1200257080 /* Operators.swift */,
);
path = "Supporting Files";
Expand All @@ -532,16 +528,17 @@
children = (
F3ABC2B92285F6D00010BAF0 /* Array+Extensions.swift */,
F38CD1BF1F8384490050056C /* Bundle+Extensions.swift */,
F33A1F4024C9866F008ED2BD /* Logger+Extensions.swift */,
F37781142085E14C00146DBE /* Optional+Extensions.swift */,
F38CD2341F83AB9E0050056C /* Reactive+Extensions.swift */,
F3CBB19521CCFFA00023EE18 /* RxSwift+WKWebView.swift */,
F3A813121F837ECF00A09AAB /* String+Extensions.swift */,
F3C5F35D2961EADD00257080 /* UIEdgeInsets+Extensions.swift */,
F3AAA6251F86113A009653B7 /* UINavigationController+Extensions.swift */,
F38CD2361F83AEC70050056C /* UIScrollView+Extensions.swift */,
F3C5F3532961BD8300257080 /* UIView+Layout.swift */,
F33EB3FD1FBDD81F0050560D /* UIViewController+Extensions.swift */,
F3C7CFDC2423AF4C003A961E /* URL+Extensions.swift */,
F3C5F35D2961EADD00257080 /* UIEdgeInsets+Extensions.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -798,7 +795,7 @@
files = (
F3C5F3572961C60A00257080 /* LibraryCell.swift in Sources */,
F3C7CFDD2423AF4C003A961E /* URL+Extensions.swift in Sources */,
F33A1F4124C9866F008ED2BD /* Log.swift in Sources */,
F33A1F4124C9866F008ED2BD /* Logger+Extensions.swift in Sources */,
F38CD1BD1F8382950050056C /* RssSourceViewModel.swift in Sources */,
F3A813021F837A8200A09AAB /* SourceSelectionViewController.swift in Sources */,
F38CD1C01F8384490050056C /* Bundle+Extensions.swift in Sources */,
Expand Down Expand Up @@ -837,7 +834,6 @@
F3A812DC1F8375DF00A09AAB /* AppCoordinator.swift in Sources */,
F3A8130B1F837B0E00A09AAB /* SetupCoordinator.swift in Sources */,
F3A812D81F8375A100A09AAB /* Coordinator.swift in Sources */,
F3D7D14B2441C599001695B9 /* DebugUtils.swift in Sources */,
F3A8130F1F837C0800A09AAB /* FeedCoordinator.swift in Sources */,
F33EB3FE1FBDD81F0050560D /* UIViewController+Extensions.swift in Sources */,
F3C5F35C2961E45000257080 /* AboutCell.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ final class LibrariesViewModel {

init() {
guard let path = Bundle.main.path(forResource: "Licenses", ofType: "plist"), let array = NSArray(contentsOfFile: path) as? [[String: Any]] else {
fail("Invalid bundle linceses file")
fatalError("Invalid bundle linceses file")
}

libraries = Observable.just(array.map {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

import Foundation
import OSLog
import Swinject
import UIKit

Expand Down Expand Up @@ -55,10 +56,10 @@ final class AppCoordinator: Coordinator {
*/
func start() {
if settingsService.selectedSource.isSome {
Log.debug("Setup complete, starting dashboard")
Logger.appFlow.debug("Setup complete, starting dashboard")
showFeed()
} else {
Log.debug("Starting setup")
Logger.appFlow.debug("Starting setup")
showSetup()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ final class UserDefaultsSettingsService: SettingsService {

let coder = JSONEncoder()
guard let data = try? coder.encode(value) else {
fail("Encoding RssSource should never fail")
fatalError("Encoding RssSource should never fail")
}

UserDefaults.standard.set(data, forKey: "source")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import FeedKit
import Foundation
import OSLog
import UIKit

final class RssDataService: DataService {
Expand All @@ -19,7 +20,7 @@ final class RssDataService: DataService {

let parser = FeedParser(URL: feedURL)

Log.debug("Loading \(feedURL.absoluteString)")
Logger.data.debug("Loading \(feedURL.absoluteString)")

parser.parseAsync(queue: DispatchQueue.global(qos: .userInitiated)) { result in
switch result {
Expand All @@ -31,7 +32,7 @@ final class RssDataService: DataService {

onCompletion(.success(items.map({ RssItem(title: $0.title, description: $0.description, link: $0.link, pubDate: $0.pubDate) })))
case let .failure(error):
Log.error("Loading data failed with \(error)")
Logger.data.error("Loading data failed with \(error)")
onCompletion(.failure(error))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ final class DetailViewController: UIViewController {
}

@available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
notImplemented()
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func loadView() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ final class FeedViewModel {

init(dataService: DataService, settingsService: SettingsService) {
guard let source = settingsService.selectedSource else {
fail("Source not selected, nothing to show in feed")
fatalError("Source not selected, nothing to show in feed")
}

// converting callback based data service call to an observable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

import Foundation
import OSLog
import RxCocoa
import RxSwift

Expand All @@ -27,7 +28,7 @@ final class SourceSelectionViewModel {
init(settingsService: SettingsService) {
self.settingsService = settingsService

Log.debug("Loading bundled sources")
Logger.data.debug("Loading bundled sources")

let jsonData = Bundle.main.loadFile(filename: "sources.json")!

Expand Down Expand Up @@ -78,7 +79,7 @@ final class SourceSelectionViewModel {

func saveSelectedSource() -> Bool {
guard let selected = allSources.value.first(where: { $0.isSelected.value }) else {
Log.error("Cannot save, no source selected")
Logger.data.error("Cannot save, no source selected")
return false
}

Expand Down
5 changes: 3 additions & 2 deletions Sources/iOSSampleApp/Supporting Files/AppDelegate+Setup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

import Foundation
import OSLog
import Swinject
import SwinjectAutoregistration

Expand All @@ -15,7 +16,7 @@ extension AppDelegate {
Set up the depedency graph in the DI container
*/
internal func setupDependencies() {
Log.debug("Registering dependencies")
Logger.appFlow.debug("Registering dependencies")

// services
container.autoregister(SettingsService.self, initializer: UserDefaultsSettingsService.init).inObjectScope(ObjectScope.container)
Expand Down Expand Up @@ -47,7 +48,7 @@ extension AppDelegate {

#if DEBUG
if ProcessInfo().arguments.contains("testMode") {
Log.debug("Running in UI tests, deleting selected source to start clean")
Logger.appFlow.debug("Running in UI tests, deleting selected source to start clean")
let settingsService = container.resolve(SettingsService.self)!
settingsService.selectedSource = nil
}
Expand Down
39 changes: 0 additions & 39 deletions Sources/iOSSampleApp/Supporting Files/DebugUtils.swift

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// Log.swift
// iOSSampleApp
//
// Created by Igor Kulman on 23/07/2020.
// Copyright © 2020 Igor Kulman. All rights reserved.
//

import Foundation
import OSLog

extension Logger {
private static var subsystem = Bundle.main.bundleIdentifier!

static let data = Logger(subsystem: subsystem, category: "data")
static let appFlow = Logger(subsystem: subsystem, category: "appFlow")
}
20 changes: 0 additions & 20 deletions Sources/iOSSampleApp/Supporting Files/Log.swift

This file was deleted.

0 comments on commit 48bc8a0

Please sign in to comment.