Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds pixels to track main VPN funnels #2543

Merged
merged 6 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion Core/Pixel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,27 @@ extension Pixel {
}
}

/// NSError supports this through `NSUnderlyingError`, but there's no support for this for Swift's `Error`. This protocol does that.
///
/// The reason why this protocol returns a code and a domain instead of just an `Error` or `NSError` is so that the error implementing
/// this protocol has full control over these values, and is able to override them as it best sees fit.
///
protocol ErrorWithUnderlyingError: Error {
var underlyingErrorCode: Int { get }
var underlyingErrorDomain: String { get }
}

extension Dictionary where Key == String, Value == String {
mutating func appendErrorPixelParams(error: Error) {
let nsError = error as NSError

self[PixelParameters.errorCode] = "\(nsError.code)"
self[PixelParameters.errorDomain] = nsError.domain

if let underlyingError = nsError.userInfo["NSUnderlyingError"] as? NSError {
if let underlyingError = error as? ErrorWithUnderlyingError {
self[PixelParameters.underlyingErrorCode] = "\(underlyingError.underlyingErrorCode)"
self[PixelParameters.underlyingErrorDomain] = underlyingError.underlyingErrorDomain
} else if let underlyingError = nsError.userInfo["NSUnderlyingError"] as? NSError {
self[PixelParameters.underlyingErrorCode] = "\(underlyingError.code)"
self[PixelParameters.underlyingErrorDomain] = underlyingError.domain
} else if let sqlErrorCode = nsError.userInfo["NSSQLiteErrorDomain"] as? NSNumber {
Expand Down
25 changes: 25 additions & 0 deletions Core/PixelEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,18 @@ extension Pixel {
case networkProtectionActiveUser
case networkProtectionNewUser

case networkProtectionControllerStartAttempt
case networkProtectionControllerStartSuccess
case networkProtectionControllerStartFailure

case networkProtectionTunnelStartAttempt
case networkProtectionTunnelStartSuccess
case networkProtectionTunnelStartFailure

case networkProtectionTunnelUpdateAttempt
case networkProtectionTunnelUpdateSuccess
case networkProtectionTunnelUpdateFailure

case networkProtectionEnableAttemptConnecting
case networkProtectionEnableAttemptSuccess
case networkProtectionEnableAttemptFailure
Expand All @@ -280,6 +292,8 @@ extension Pixel {

case networkProtectionBreakageReport

case networkProtectionRekeyAttempt
case networkProtectionRekeyFailure
case networkProtectionRekeyCompleted

case networkProtectionTunnelConfigurationNoServerRegistrationInfo
Expand Down Expand Up @@ -785,14 +799,25 @@ extension Pixel.Event {

case .networkProtectionActiveUser: return "m_netp_daily_active_d"
case .networkProtectionNewUser: return "m_netp_daily_active_u"
case .networkProtectionControllerStartAttempt: return "m_netp_controller_start_attempt"
case .networkProtectionControllerStartSuccess: return "m_netp_controller_start_success"
case .networkProtectionControllerStartFailure: return "m_netp_controller_start_failure"
case .networkProtectionTunnelStartAttempt: return "m_netp_tunnel_start_attempt"
case .networkProtectionTunnelStartSuccess: return "m_netp_tunnel_start_success"
case .networkProtectionTunnelStartFailure: return "m_netp_tunnel_start_failure"
case .networkProtectionTunnelUpdateAttempt: return "m_netp_tunnel_update_attempt"
case .networkProtectionTunnelUpdateSuccess: return "m_netp_tunnel_update_success"
case .networkProtectionTunnelUpdateFailure: return "m_netp_tunnel_update_failure"
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 .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"
case .networkProtectionLatencyError: return "m_netp_ev_latency_error_d"
case .networkProtectionRekeyAttempt: return "m_mac_netp_rekey_attempt"
case .networkProtectionRekeyCompleted: return "m_netp_rekey_completed"
case .networkProtectionRekeyFailure: return "m_netp_rekey_failure"
case .networkProtectionEnabledOnSearch: return "m_netp_ev_enabled_on_search"
case .networkProtectionBreakageReport: return "m_vpn_breakage_report"
case .networkProtectionTunnelConfigurationNoServerRegistrationInfo: return "m_netp_tunnel_config_error_no_server_registration_info"
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9981,7 +9981,7 @@
repositoryURL = "https://github.com/DuckDuckGo/BrowserServicesKit";
requirement = {
kind = exactVersion;
version = 114.1.0;
version = "114.1.0-1";
};
};
B6F997C22B8F374300476735 /* XCRemoteSwiftPackageReference "apple-toolbox" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/DuckDuckGo/BrowserServicesKit",
"state" : {
"revision" : "045a8782c3dbbf79fc088b38120dea1efadc13e1",
"version" : "114.1.0"
"revision" : "d9de416d3b77082f818a91b065bee1a2025c8e46",
"version" : "114.1.0-1"
}
},
{
Expand Down
5 changes: 5 additions & 0 deletions DuckDuckGo/NetworkProtectionTunnelController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,14 @@ final class NetworkProtectionTunnelController: TunnelController {
/// Starts the VPN connection used for Network Protection
///
func start() async {
Pixel.fire(pixel: .networkProtectionControllerStartAttempt)

do {
try await startWithError()
Pixel.fire(pixel: .networkProtectionControllerStartSuccess)
} catch {
Pixel.fire(pixel: .networkProtectionControllerStartFailure, error: error)

#if DEBUG
errorStore.lastErrorMessage = error.localizedDescription
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import NetworkExtension
import NetworkProtection
import Subscription

// swiftlint:disable type_body_length

// Initial implementation for initial Network Protection tests. Will be fleshed out with https://app.asana.com/0/1203137811378537/1204630829332227/f
final class NetworkProtectionPacketTunnelProvider: PacketTunnelProvider {

Expand Down Expand Up @@ -68,8 +70,33 @@ final class NetworkProtectionPacketTunnelProvider: PacketTunnelProvider {
guard quality != .unknown else { return }
DailyPixel.fireDailyAndCount(pixel: .networkProtectionLatency(quality: quality))
}
case .rekeyCompleted:
Pixel.fire(pixel: .networkProtectionRekeyCompleted)
case .rekeyAttempt(let step):
switch step {
case .begin:
DailyPixel.fireDailyAndCount(pixel: .networkProtectionRekeyAttempt)
case .failure(let error):
DailyPixel.fireDailyAndCount(pixel: .networkProtectionRekeyFailure, error: error)
case .success:
DailyPixel.fireDailyAndCount(pixel: .networkProtectionRekeyCompleted)
}
case .tunnelStartAttempt(let step):
switch step {
case .begin:
DailyPixel.fireDailyAndCount(pixel: .networkProtectionTunnelStartAttempt)
case .failure(let error):
DailyPixel.fireDailyAndCount(pixel: .networkProtectionTunnelStartFailure, error: error)
case .success:
DailyPixel.fireDailyAndCount(pixel: .networkProtectionTunnelStartSuccess)
}
case .tunnelUpdateAttempt(let step):
switch step {
case .begin:
DailyPixel.fireDailyAndCount(pixel: .networkProtectionTunnelUpdateAttempt)
case .failure(let error):
DailyPixel.fireDailyAndCount(pixel: .networkProtectionTunnelUpdateFailure, error: error)
case .success:
DailyPixel.fireDailyAndCount(pixel: .networkProtectionTunnelUpdateSuccess)
}
}
}

Expand Down Expand Up @@ -287,4 +314,6 @@ final class NetworkProtectionPacketTunnelProvider: PacketTunnelProvider {
}
}

// swiftlint:enable type_body_length

#endif
Loading