FieldBackgroundExecutionUITestProbe.swift (5255B)
1 import Foundation 2 import RadrootsKit 3 4 enum FieldBackgroundExecutionUITestProbe { 5 private static let enabledKey = "RADROOTS_FIELD_IOS_UI_TEST_BACKGROUND_EXECUTION_PROBE" 6 private static let redactionPolicy = RadrootsTelemetryRedactionPolicy.default 7 8 static var isRequested: Bool { 9 ProcessInfo.processInfo.environment[enabledKey] == "true" 10 } 11 12 static func value( 13 registered: Bool, 14 scheduledTaskCount: Int, 15 pendingBeforeMaintenance: Int, 16 pendingBeforeCancel: Int, 17 pendingAfterCancel: Int, 18 cancellationObserved: Bool, 19 stagedBlobRemoved: Bool, 20 transferSnapshotCount: Int, 21 events: [RadrootsTelemetryEvent] 22 ) -> String { 23 let eventNames = Set(events.map(\.name)) 24 let values = events.flatMap(stringValues) 25 return [ 26 "registered=\(registered)", 27 "scheduled_task_count=\(scheduledTaskCount)", 28 "schedule_observed=\(scheduledTaskCount >= 2)", 29 "pending_before_maintenance=\(pendingBeforeMaintenance)", 30 "pending_before_cancel=\(pendingBeforeCancel)", 31 "pending_after_cancel=\(pendingAfterCancel)", 32 "cancellation_observed=\(cancellationObserved)", 33 "staged_blob_removed=\(stagedBlobRemoved)", 34 "transfer_snapshot_count=\(transferSnapshotCount)", 35 "background_register_seen=\(eventNames.contains("field_ios.background_execution.handler_registration"))", 36 "background_schedule_seen=\(eventNames.contains("field_ios.background_execution.schedule"))", 37 "background_cancel_all_seen=\(eventNames.contains("field_ios.background_execution.cancel_all"))", 38 "background_transfer_inspect_seen=\(eventNames.contains("field_ios.background_execution.transfer_inspect"))", 39 "background_staged_blob_sweep_seen=\(eventNames.contains("field_ios.background_execution.staged_blob_sweep"))", 40 "background_relay_refresh_seen=\(eventNames.contains("field_ios.background_execution.relay_refresh"))", 41 "background_maintenance_seen=\(eventNames.contains("field_ios.background_execution.maintenance"))", 42 "unsafe_values_present=\(values.contains(where: containsUnsafeValue))", 43 "relay_url_values_present=\(values.contains(where: containsRelayURL))", 44 "secret_like_values_present=\(values.contains(where: containsSecretLikeValue))", 45 "path_like_values_present=\(values.contains(where: containsPathLikeValue))", 46 "npub_values_present=\(values.contains(where: containsNpubValue))" 47 ].joined(separator: ";") 48 } 49 50 static func failureValue(outcome: String) -> String { 51 [ 52 "registered=false", 53 "scheduled_task_count=0", 54 "schedule_observed=false", 55 "pending_before_maintenance=0", 56 "pending_before_cancel=0", 57 "pending_after_cancel=0", 58 "cancellation_observed=false", 59 "staged_blob_removed=false", 60 "transfer_snapshot_count=0", 61 "background_register_seen=false", 62 "background_schedule_seen=false", 63 "background_cancel_all_seen=false", 64 "background_transfer_inspect_seen=false", 65 "background_staged_blob_sweep_seen=false", 66 "background_relay_refresh_seen=false", 67 "background_maintenance_seen=false", 68 "probe_failure_outcome=\(outcome)", 69 "unsafe_values_present=false", 70 "relay_url_values_present=false", 71 "secret_like_values_present=false", 72 "path_like_values_present=false", 73 "npub_values_present=false" 74 ].joined(separator: ";") 75 } 76 77 private static func stringValues(from event: RadrootsTelemetryEvent) -> [String] { 78 var values = event.message.map { [$0] } ?? [] 79 values.append(contentsOf: event.fields.map { field in 80 field.value.renderedValue 81 }) 82 return values 83 } 84 85 private static func containsUnsafeValue(_ value: String) -> Bool { 86 redactionPolicy.containsUnsafeValue(value) 87 || containsRelayURL(value) 88 || containsSecretLikeValue(value) 89 || containsPathLikeValue(value) 90 || containsNpubValue(value) 91 } 92 93 private static func containsRelayURL(_ value: String) -> Bool { 94 let normalized = value.lowercased() 95 return normalized.contains("ws://") || normalized.contains("wss://") 96 } 97 98 private static func containsSecretLikeValue(_ value: String) -> Bool { 99 let normalized = value.lowercased() 100 return normalized.contains("nsec") 101 || normalized.range(of: "[a-f0-9]{64}", options: .regularExpression) != nil 102 } 103 104 private static func containsPathLikeValue(_ value: String) -> Bool { 105 let normalized = value.lowercased() 106 return normalized.contains("/users/") 107 || normalized.contains("/private/var/") 108 || normalized.contains("/var/mobile/containers/") 109 || normalized.contains("/var/folders/") 110 || normalized.contains("file:///") 111 } 112 113 private static func containsNpubValue(_ value: String) -> Bool { 114 value.lowercased().contains("npub") 115 } 116 }