diff --git a/Core/PixelEvent.swift b/Core/PixelEvent.swift index 8b6ca67604..1d553eea15 100644 --- a/Core/PixelEvent.swift +++ b/Core/PixelEvent.swift @@ -337,6 +337,11 @@ extension Pixel { case networkProtectionServerMigrationAttemptSuccess case networkProtectionServerMigrationAttemptFailure + case networkProtectionConnectionTesterFailureDetected + case networkProtectionConnectionTesterFailureRecovered(failureCount: Int) + case networkProtectionConnectionTesterExtendedFailureDetected + case networkProtectionConnectionTesterExtendedFailureRecovered(failureCount: Int) + case networkProtectionTunnelFailureDetected case networkProtectionTunnelFailureRecovered @@ -1043,6 +1048,10 @@ extension Pixel.Event { case .networkProtectionEnableAttemptConnecting: return "m_netp_ev_enable_attempt" case .networkProtectionEnableAttemptSuccess: return "m_netp_ev_enable_attempt_success" case .networkProtectionEnableAttemptFailure: return "m_netp_ev_enable_attempt_failure" + case .networkProtectionConnectionTesterFailureDetected: return "m_netp_connection_tester_failure" + case .networkProtectionConnectionTesterFailureRecovered: return "m_netp_connection_tester_failure_recovered" + case .networkProtectionConnectionTesterExtendedFailureDetected: return "m_netp_connection_tester_extended_failure" + case .networkProtectionConnectionTesterExtendedFailureRecovered: return "m_netp_connection_tester_extended_failure_recovered" case .networkProtectionTunnelFailureDetected: return "m_netp_ev_tunnel_failure" case .networkProtectionTunnelFailureRecovered: return "m_netp_ev_tunnel_failure_recovered" case .networkProtectionLatency(let quality): return "m_netp_ev_\(quality.rawValue)_latency" diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 3c9f071b41..d99b9972f5 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -9946,7 +9946,7 @@ repositoryURL = "https://github.com/DuckDuckGo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 167.0.0; + version = 167.0.1; }; }; 9F8FE9472BAE50E50071E372 /* XCRemoteSwiftPackageReference "lottie-spm" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d69794d5b7..6d2d55714a 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/DuckDuckGo/BrowserServicesKit", "state" : { - "revision" : "5954412504b0cf294f5c0d90d7a0c8dfcd009558", - "version" : "167.0.0" + "revision" : "0746af01b77d39a1e037bea93b46591534a13b5c", + "version" : "167.0.1" } }, { diff --git a/PacketTunnelProvider/NetworkProtection/NetworkProtectionPacketTunnelProvider.swift b/PacketTunnelProvider/NetworkProtection/NetworkProtectionPacketTunnelProvider.swift index 8ef890d60c..4f2a0eaa5c 100644 --- a/PacketTunnelProvider/NetworkProtection/NetworkProtectionPacketTunnelProvider.swift +++ b/PacketTunnelProvider/NetworkProtection/NetworkProtectionPacketTunnelProvider.swift @@ -48,6 +48,40 @@ final class NetworkProtectionPacketTunnelProvider: PacketTunnelProvider { DailyPixel.fire(pixel: .networkProtectionActiveUser, withAdditionalParameters: [PixelParameters.vpnCohort: UniquePixel.cohort(from: defaults.vpnFirstEnabled)], includedParameters: [.appVersion, .atb]) + case .connectionTesterStatusChange(let status, let server): + vpnLogger.log(status, server: server) + + switch status { + case .failed(let duration): + let pixel: Pixel.Event = { + switch duration { + case .immediate: + return .networkProtectionConnectionTesterFailureDetected + case .extended: + return .networkProtectionConnectionTesterExtendedFailureDetected + } + }() + + DailyPixel.fireDailyAndCount(pixel: pixel, + withAdditionalParameters: [PixelParameters.server: server], + includedParameters: [.appVersion, .atb]) + case .recovered(let duration, let failureCount): + let pixel: Pixel.Event = { + switch duration { + case .immediate: + return .networkProtectionConnectionTesterFailureRecovered(failureCount: failureCount) + case .extended: + return .networkProtectionConnectionTesterExtendedFailureRecovered(failureCount: failureCount) + } + }() + + DailyPixel.fireDailyAndCount(pixel: pixel, + withAdditionalParameters: [ + PixelParameters.count: String(failureCount), + PixelParameters.server: server + ], + includedParameters: [.appVersion, .atb]) + } case .reportConnectionAttempt(attempt: let attempt): vpnLogger.log(attempt) diff --git a/PacketTunnelProvider/NetworkProtection/VPNLogger.swift b/PacketTunnelProvider/NetworkProtection/VPNLogger.swift index e60e048d4e..e45a30a8eb 100644 --- a/PacketTunnelProvider/NetworkProtection/VPNLogger.swift +++ b/PacketTunnelProvider/NetworkProtection/VPNLogger.swift @@ -30,6 +30,7 @@ import OSLog public final class VPNLogger { public typealias AttemptStep = PacketTunnelProvider.AttemptStep public typealias ConnectionAttempt = PacketTunnelProvider.ConnectionAttempt + public typealias ConnectionTesterStatus = PacketTunnelProvider.ConnectionTesterStatus public typealias LogCallback = (OSLogType, OSLogMessage) -> Void public init() {} @@ -64,6 +65,21 @@ public final class VPNLogger { } } + public func log(_ status: ConnectionTesterStatus, server: String) { + let log = OSLog.networkProtectionConnectionTesterLog + + switch status { + case .failed(let duration): + os_log("🔴 Connection tester (%{public}@ - %{public}@) failure", log: log, type: .error, duration.rawValue, server) + case .recovered(let duration, let failureCount): + os_log("🟢 Connection tester (%{public}@ - %{public}@) recovery (after %{public}@ failures)", + log: log, + duration.rawValue, + server, + String(failureCount)) + } + } + public func log(_ step: FailureRecoveryStep) { let log = OSLog.networkProtectionTunnelFailureMonitorLog