Fine-tune important logging categories (#825)
- .App.profiles for profiles management - .App.iap for in-app purchases
This commit is contained in:
parent
5949ff1508
commit
c32dcd6565
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue