Fine-tune important logging categories (#825)

- .App.profiles for profiles management
- .App.iap for in-app purchases
This commit is contained in:
Davide 2024-11-07 11:33:20 +01:00 committed by GitHub
parent 5949ff1508
commit c32dcd6565
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 66 additions and 62 deletions

View File

@ -46,7 +46,7 @@ public final class InMemoryProfileRepository: ProfileRepository {
}
public func saveProfile(_ profile: Profile) {
pp_log(.app, .info, "Save profile: \(profile.id))")
pp_log(.App.profiles, .info, "Save profile: \(profile.id))")
if let index = profiles.firstIndex(where: { $0.id == profile.id }) {
profiles[index] = profile
} else {
@ -55,7 +55,7 @@ public final class InMemoryProfileRepository: ProfileRepository {
}
public func removeProfiles(withIds ids: [Profile.ID]) {
pp_log(.app, .info, "Remove profiles: \(ids)")
pp_log(.App.profiles, .info, "Remove profiles: \(ids)")
profiles = profiles.filter {
!ids.contains($0.id)
}

View File

@ -92,10 +92,10 @@ private extension NEProfileRepository {
let profiles = managers.values.compactMap {
do {
let profile = try repository.profile(from: $0)
pp_log(.app, .debug, "Attributes for profile \(profile.id): \(profile.attributes)")
pp_log(.App.profiles, .debug, "Attributes for profile \(profile.id): \(profile.attributes)")
return profile
} catch {
pp_log(.app, .error, "Unable to decode profile from NE manager '\($0.localizedDescription ?? "")': \(error)")
pp_log(.App.profiles, .error, "Unable to decode profile from NE manager '\($0.localizedDescription ?? "")': \(error)")
return nil
}
}
@ -119,7 +119,7 @@ private extension NEProfileRepository {
}
if !removedProfilesDescription.isEmpty {
pp_log(.app, .info, "Sync profiles removed externally: \(removedProfilesDescription)")
pp_log(.App.profiles, .info, "Sync profiles removed externally: \(removedProfilesDescription)")
}
profilesSubject.send(profiles)

View File

@ -144,7 +144,7 @@ extension ProfileManager {
profile = originalProfile
}
pp_log(.app, .notice, "Save profile \(profile.id)...")
pp_log(.App.profiles, .notice, "Save profile \(profile.id)...")
do {
let existingProfile = allProfiles[profile.id]
if existingProfile == nil || profile != existingProfile {
@ -157,27 +157,27 @@ extension ProfileManager {
allProfiles[profile.id] = profile
didChange.send(.save(profile))
} else {
pp_log(.app, .notice, "\tProfile \(profile.id) not modified, not saving")
pp_log(.App.profiles, .notice, "\tProfile \(profile.id) not modified, not saving")
}
} catch {
pp_log(.app, .fault, "\tUnable to save profile \(profile.id): \(error)")
pp_log(.App.profiles, .fault, "\tUnable to save profile \(profile.id): \(error)")
throw error
}
do {
if let isShared, let remoteRepository {
if isShared {
pp_log(.app, .notice, "\tEnable remote sharing of profile \(profile.id)...")
pp_log(.App.profiles, .notice, "\tEnable remote sharing of profile \(profile.id)...")
try await remoteRepository.saveProfile(profile)
} else {
pp_log(.app, .notice, "\tDisable remote sharing of profile \(profile.id)...")
pp_log(.App.profiles, .notice, "\tDisable remote sharing of profile \(profile.id)...")
try await remoteRepository.removeProfiles(withIds: [profile.id])
}
}
} catch {
pp_log(.app, .fault, "\tUnable to save/remove remote profile \(profile.id): \(error)")
pp_log(.App.profiles, .fault, "\tUnable to save/remove remote profile \(profile.id): \(error)")
throw error
}
pp_log(.app, .notice, "Finished saving profile \(profile.id)")
pp_log(.App.profiles, .notice, "Finished saving profile \(profile.id)")
}
public func remove(withId profileId: Profile.ID) async {
@ -185,7 +185,7 @@ extension ProfileManager {
}
public func remove(withIds profileIds: [Profile.ID]) async {
pp_log(.app, .notice, "Remove profiles \(profileIds)...")
pp_log(.App.profiles, .notice, "Remove profiles \(profileIds)...")
do {
// remove local profiles
var newAllProfiles = allProfiles
@ -204,7 +204,7 @@ extension ProfileManager {
allProfiles = newAllProfiles
didChange.send(.remove(profileIds))
} catch {
pp_log(.app, .fault, "Unable to remove profiles \(profileIds): \(error)")
pp_log(.App.profiles, .fault, "Unable to remove profiles \(profileIds): \(error)")
}
}
@ -225,7 +225,7 @@ extension ProfileManager {
}
public func eraseRemotelySharedProfiles() async throws {
pp_log(.app, .notice, "Erase remotely shared profiles...")
pp_log(.App.profiles, .notice, "Erase remotely shared profiles...")
try await remoteRepository?.removeProfiles(withIds: Array(allRemoteProfiles.keys))
}
}
@ -250,7 +250,7 @@ extension ProfileManager {
var builder = profile.builder(withNewId: true)
builder.name = firstUniqueName(from: profile.name)
pp_log(.app, .notice, "Duplicate profile [\(profileId), \(profile.name)] -> [\(builder.id), \(builder.name)]...")
pp_log(.App.profiles, .notice, "Duplicate profile [\(profileId), \(profile.name)] -> [\(builder.id), \(builder.name)]...")
let copy = try builder.tryBuild()
try await save(copy)
@ -316,7 +316,7 @@ extension ProfileManager {
private extension ProfileManager {
func reloadLocalProfiles(_ result: [Profile]) {
pp_log(.app, .info, "Reload local profiles: \(result.map(\.id))")
pp_log(.App.profiles, .info, "Reload local profiles: \(result.map(\.id))")
allProfiles = result.reduce(into: [:]) {
$0[$1.id] = $1
}
@ -330,7 +330,7 @@ private extension ProfileManager {
.map(\.key)
if !idsToRemove.isEmpty {
pp_log(.app, .info, "Delete non-included local profiles: \(idsToRemove)")
pp_log(.App.profiles, .info, "Delete non-included local profiles: \(idsToRemove)")
Task.detached {
try await self.repository.removeProfiles(withIds: idsToRemove)
}
@ -339,7 +339,7 @@ private extension ProfileManager {
}
func loadInitialRemoteProfiles(_ result: [Profile]) {
pp_log(.app, .info, "Load initial remote profiles: \(result.map(\.id))")
pp_log(.App.profiles, .info, "Load initial remote profiles: \(result.map(\.id))")
allRemoteProfiles = result.reduce(into: [:]) {
$0[$1.id] = $1
}
@ -347,7 +347,7 @@ private extension ProfileManager {
}
func reloadRemoteProfiles(_ result: [Profile]) {
pp_log(.app, .info, "Reload remote profiles: \(result.map(\.id))")
pp_log(.App.profiles, .info, "Reload remote profiles: \(result.map(\.id))")
allRemoteProfiles = result.reduce(into: [:]) {
$0[$1.id] = $1
}
@ -358,17 +358,17 @@ private extension ProfileManager {
return
}
pp_log(.app, .info, "Start importing remote profiles...")
pp_log(.App.profiles, .info, "Start importing remote profiles...")
pp_log(.app, .debug, "Local fingerprints:")
pp_log(.App.profiles, .debug, "Local fingerprints:")
let localFingerprints: [Profile.ID: UUID] = await allProfiles.values.reduce(into: [:]) {
$0[$1.id] = $1.attributes.fingerprint
pp_log(.app, .debug, "\t\($1.id) = \($1.attributes.fingerprint?.description ?? "nil")")
pp_log(.App.profiles, .debug, "\t\($1.id) = \($1.attributes.fingerprint?.description ?? "nil")")
}
pp_log(.app, .debug, "Remote fingerprints:")
pp_log(.App.profiles, .debug, "Remote fingerprints:")
let remoteFingerprints: [Profile.ID: UUID] = result.reduce(into: [:]) {
$0[$1.id] = $1.attributes.fingerprint
pp_log(.app, .debug, "\t\($1.id) = \($1.attributes.fingerprint?.description ?? "nil")")
pp_log(.App.profiles, .debug, "\t\($1.id) = \($1.attributes.fingerprint?.description ?? "nil")")
}
let profilesToImport = result
@ -377,7 +377,7 @@ private extension ProfileManager {
var idsToRemove: [Profile.ID] = []
if !remotelyDeletedIds.isEmpty {
pp_log(.app, .info, "Will \(deletingRemotely ? "delete" : "retain") local profiles not present in remote repository: \(remotelyDeletedIds)")
pp_log(.App.profiles, .info, "Will \(deletingRemotely ? "delete" : "retain") local profiles not present in remote repository: \(remotelyDeletedIds)")
if deletingRemotely {
idsToRemove.append(contentsOf: remotelyDeletedIds)
@ -386,27 +386,27 @@ private extension ProfileManager {
for remoteProfile in profilesToImport {
do {
guard processor?.isIncluded(remoteProfile) ?? true else {
pp_log(.app, .info, "Will delete non-included remote profile \(remoteProfile.id)")
pp_log(.App.profiles, .info, "Will delete non-included remote profile \(remoteProfile.id)")
idsToRemove.append(remoteProfile.id)
continue
}
guard remoteFingerprints[remoteProfile.id] != localFingerprints[remoteProfile.id] else {
pp_log(.app, .info, "Skip re-importing local profile \(remoteProfile.id)")
pp_log(.App.profiles, .info, "Skip re-importing local profile \(remoteProfile.id)")
continue
}
pp_log(.app, .notice, "Import remote profile \(remoteProfile.id)...")
pp_log(.App.profiles, .notice, "Import remote profile \(remoteProfile.id)...")
try await save(remoteProfile)
} catch {
pp_log(.app, .error, "Unable to import remote profile: \(error)")
pp_log(.App.profiles, .error, "Unable to import remote profile: \(error)")
}
}
pp_log(.app, .notice, "Finished importing remote profiles, delete stale profiles: \(idsToRemove)")
pp_log(.App.profiles, .notice, "Finished importing remote profiles, delete stale profiles: \(idsToRemove)")
try? await repository.removeProfiles(withIds: idsToRemove)
}
}
func performSearch(_ search: String) {
pp_log(.app, .notice, "Filter profiles with '\(search)'")
pp_log(.App.profiles, .notice, "Filter profiles with '\(search)'")
reloadFilteredProfiles(with: search)
}

View File

@ -73,7 +73,7 @@ extension ProfileAttributes: ProfileUserInfoTransformable {
let data = try JSONEncoder().encode(self)
return try JSONSerialization.jsonObject(with: data) as? [String: AnyHashable] ?? [:]
} catch {
pp_log(.app, .error, "Unable to encode ProfileAttributes to dictionary: \(error)")
pp_log(.App.profiles, .error, "Unable to encode ProfileAttributes to dictionary: \(error)")
return [:]
}
}
@ -83,7 +83,7 @@ extension ProfileAttributes: ProfileUserInfoTransformable {
let data = try JSONSerialization.data(withJSONObject: userInfo ?? [:])
self = try JSONDecoder().decode(ProfileAttributes.self, from: data)
} catch {
pp_log(.app, .error, "Unable to decode ProfileAttributes from dictionary: \(error)")
pp_log(.App.profiles, .error, "Unable to decode ProfileAttributes from dictionary: \(error)")
return nil
}
}

View File

@ -60,14 +60,14 @@ private extension FallbackReceiptReader {
func asyncReceipt(at userLevel: AppUserLevel) async -> InAppReceipt? {
let localURL = Bundle.main.appStoreReceiptURL
pp_log(.iap, .debug, "\tParse receipt for user level \(userLevel)")
pp_log(.App.iap, .debug, "\tParse receipt for user level \(userLevel)")
// 1. TestFlight, look for release receipt
let releaseReceipt: InAppReceipt? = await {
guard userLevel == .beta, let localURL else {
return nil
}
pp_log(.iap, .debug, "\tTestFlight, look for release receipt")
pp_log(.App.iap, .debug, "\tTestFlight, look for release receipt")
let releaseURL = localURL
.deletingLastPathComponent()
.appendingPathComponent("receipt")
@ -83,7 +83,7 @@ private extension FallbackReceiptReader {
}()
if let releaseReceipt {
pp_log(.iap, .debug, "\tTestFlight, return release receipt")
pp_log(.App.iap, .debug, "\tTestFlight, return release receipt")
return releaseReceipt
}
@ -95,18 +95,18 @@ private extension FallbackReceiptReader {
}
// 2. primary receipt + build from local receipt
pp_log(.iap, .debug, "\tNo release receipt, read primary receipt")
pp_log(.App.iap, .debug, "\tNo release receipt, read primary receipt")
if let receipt = await reader?.receipt() {
if let build = await localReceiptBlock()?.originalBuildNumber {
pp_log(.iap, .debug, "\tReturn primary receipt with local build: \(build)")
pp_log(.App.iap, .debug, "\tReturn primary receipt with local build: \(build)")
return receipt.withBuildNumber(build)
}
pp_log(.iap, .debug, "\tReturn primary receipt without local build")
pp_log(.App.iap, .debug, "\tReturn primary receipt without local build")
return receipt
}
// 3. fall back to local receipt
pp_log(.iap, .debug, "\tReturn local receipt")
pp_log(.App.iap, .debug, "\tReturn local receipt")
return await localReceiptBlock()
}
}

View File

@ -83,7 +83,7 @@ extension IAPManager {
inAppProducts[$0]
}
} catch {
pp_log(.iap, .error, "Unable to fetch in-app products: \(error)")
pp_log(.App.iap, .error, "Unable to fetch in-app products: \(error)")
return []
}
}
@ -159,7 +159,7 @@ extension IAPManager {
private extension IAPManager {
func asyncReloadReceipt() async {
pp_log(.iap, .notice, "Start reloading in-app receipt...")
pp_log(.App.iap, .notice, "Start reloading in-app receipt...")
purchasedAppBuild = nil
purchasedProducts.removeAll()
@ -171,41 +171,41 @@ private extension IAPManager {
}
if let purchasedAppBuild {
pp_log(.iap, .info, "Original purchased build: \(purchasedAppBuild)")
pp_log(.App.iap, .info, "Original purchased build: \(purchasedAppBuild)")
// assume some purchases by build number
let entitled = productsAtBuild?(purchasedAppBuild) ?? []
pp_log(.iap, .notice, "Entitled features: \(entitled.map(\.rawValue))")
pp_log(.App.iap, .notice, "Entitled features: \(entitled.map(\.rawValue))")
entitled.forEach {
purchasedProducts.insert($0)
}
}
if let iapReceipts = receipt.purchaseReceipts {
pp_log(.iap, .info, "Process in-app purchase receipts...")
pp_log(.App.iap, .info, "Process in-app purchase receipts...")
let products: [AppProduct] = iapReceipts.compactMap {
guard let pid = $0.productIdentifier else {
return nil
}
guard let product = AppProduct(rawValue: pid) else {
pp_log(.iap, .debug, "\tDiscard unknown product identifier: \(pid)")
pp_log(.App.iap, .debug, "\tDiscard unknown product identifier: \(pid)")
return nil
}
if let expirationDate = $0.expirationDate {
let now = Date()
pp_log(.iap, .debug, "\t\(pid) [expiration date: \(expirationDate), now: \(now)]")
pp_log(.App.iap, .debug, "\t\(pid) [expiration date: \(expirationDate), now: \(now)]")
if now >= expirationDate {
pp_log(.iap, .info, "\t\(pid) [expired on: \(expirationDate)]")
pp_log(.App.iap, .info, "\t\(pid) [expired on: \(expirationDate)]")
return nil
}
}
if let cancellationDate = $0.cancellationDate {
pp_log(.iap, .info, "\t\(pid) [cancelled on: \(cancellationDate)]")
pp_log(.App.iap, .info, "\t\(pid) [cancelled on: \(cancellationDate)]")
return nil
}
if let purchaseDate = $0.originalPurchaseDate {
pp_log(.iap, .info, "\t\(pid) [purchased on: \(purchaseDate)]")
pp_log(.App.iap, .info, "\t\(pid) [purchased on: \(purchaseDate)]")
}
return product
}
@ -221,7 +221,7 @@ private extension IAPManager {
}
}
} else {
pp_log(.iap, .error, "Could not parse App Store receipt!")
pp_log(.App.iap, .error, "Could not parse App Store receipt!")
}
userLevel.features.forEach {
@ -231,10 +231,10 @@ private extension IAPManager {
eligibleFeatures.insert($0)
}
pp_log(.iap, .notice, "Finished reloading in-app receipt for user level \(userLevel)")
pp_log(.iap, .notice, "\tPurchased build number: \(purchasedAppBuild?.description ?? "unknown")")
pp_log(.iap, .notice, "\tPurchased products: \(purchasedProducts.map(\.rawValue))")
pp_log(.iap, .notice, "\tEligible features: \(eligibleFeatures)")
pp_log(.App.iap, .notice, "Finished reloading in-app receipt for user level \(userLevel)")
pp_log(.App.iap, .notice, "\tPurchased build number: \(purchasedAppBuild?.description ?? "unknown")")
pp_log(.App.iap, .notice, "\tPurchased products: \(purchasedProducts.map(\.rawValue))")
pp_log(.App.iap, .notice, "\tEligible features: \(eligibleFeatures)")
objectWillChange.send()
}
@ -249,7 +249,7 @@ private extension IAPManager {
await reloadReceipt()
do {
let products = try await inAppHelper.fetchProducts()
pp_log(.iap, .info, "Available in-app products: \(products.map(\.key))")
pp_log(.App.iap, .info, "Available in-app products: \(products.map(\.key))")
inAppHelper
.didUpdate
@ -262,7 +262,7 @@ private extension IAPManager {
.store(in: &subscriptions)
} catch {
pp_log(.iap, .error, "Unable to fetch in-app products: \(error)")
pp_log(.App.iap, .error, "Unable to fetch in-app products: \(error)")
}
}
}
@ -273,11 +273,11 @@ private extension IAPManager {
}
if let customUserLevel {
userLevel = customUserLevel
pp_log(.iap, .info, "App level (custom): \(userLevel)")
pp_log(.App.iap, .info, "App level (custom): \(userLevel)")
} else {
let isBeta = await SandboxChecker().isBeta
userLevel = isBeta ? .beta : .freemium
pp_log(.iap, .info, "App level: \(userLevel)")
pp_log(.App.iap, .info, "App level: \(userLevel)")
}
}
}

View File

@ -28,9 +28,13 @@ import PassepartoutKit
import PassepartoutWireGuardGo
extension LoggerDestination {
public static let app = Self(category: "app")
public static let app = LoggerDestination(category: "app")
public static let iap = Self(category: "iap")
public enum App {
public static let iap = LoggerDestination(category: "app.iap")
public static let profiles = LoggerDestination(category: "app.profiles")
}
}
extension WireGuard.Configuration.Builder {