Files

181 lines
7.3 KiB
Swift

//
// SnowplowLogger.swift
// PrivadoVPN
//
// Created by Zhandos Bolatbekov on 09.08.2021.
// Copyright © 2021 Privado LLC. All rights reserved.
//
import Foundation
import SnowplowTracker
// https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/mobile-trackers/migration-guides/migration-guide-for-snowplow-ios-tracker-sdk-from-version-1-x-to-2-0/
final class SnowplowLogger: EventCometLoggerProtocol, VPNCometLoggerProtocol {
private enum Constants {
enum Param {
static let name = "name"
static let value = "value"
static let extradata = "extradata"
static let appversion = "appversion"
static let timestamp = "timestamp"
static let vpnlocation = "vpnlocation"
static let vpnserver = "vpnserver"
static let vpnprotocol = "vpnprotocol"
}
enum Schema {
static let application = "iglu:io.privado/apps-application/jsonschema/1-0-0"
static let connection = "iglu:io.privado/apps-vpnconnection/jsonschema/1-0-0"
static let account = "iglu:io.privado/apps-account/jsonschema/1-0-0"
}
}
var type: CometLoggerType = .crash
var isActive = true
private static let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
formatter.calendar = Calendar(identifier: .iso8601)
return formatter
}()
private lazy var tracker: TrackerController = {
let network = NetworkConfiguration(endpoint: PrivadoConstants.Snowplow.host, method: .get)
let subject = SubjectConfiguration()
subject.userId = UUID().uuidString
subject.useragent = "App-Version: \(Environment.shortVersion) (\(Environment.bundleVersion)); OS-Version: \(Environment.operationSystem)"
let tracker = TrackerConfiguration()
.devicePlatform(.mobile)
.platformContext(false)
.geoLocationContext(false)
.screenContext(false)
.screenViewAutotracking(false)
.base64Encoding(false)
.appId(PrivadoConstants.Snowplow.appId)
return Snowplow.createTracker(namespace: PrivadoConstants.Snowplow.namespace,
network: network,
configurations: [subject, tracker])
}()
// MARK: - EventComet
func event(name: String, attributes: [String: Any], secured: [String: Any]?) {
guard self.isActive else { return }
guard name.contains(PrivadoConstants.Event.Statistic.prefix) else { return }
switch name {
case PrivadoConstants.Event.Statistic.Application.start:
self.track(applicationEvent: "AppStartupTrackEvent", attributes: attributes)
case PrivadoConstants.Event.Statistic.Application.killswitch:
self.track(applicationEvent: "KillSwitchExecuteTrackEvent", attributes: attributes)
case PrivadoConstants.Event.Statistic.Application.settings:
self.track(applicationEvent: "SaveSettingsTrackEvent", attributes: attributes)
case PrivadoConstants.Event.Statistic.Account.login:
self.track(accountEvent: "LoginTrackEvent", attributes: attributes)
case PrivadoConstants.Event.Statistic.Account.logout:
self.track(accountEvent: "LogoutTrackEvent", attributes: attributes)
case PrivadoConstants.Event.Statistic.Account.create:
self.track(accountEvent: "CreateFreemiumTrackEvent", attributes: attributes)
case PrivadoConstants.Event.Statistic.Application.premiumClicked:
self.track(applicationEvent: "PremiumServerClick", attributes: attributes)
case PrivadoConstants.Event.Statistic.Application.CTAClick:
self.track(applicationEvent: "CTAButtonClick", attributes: attributes)
default:
break
}
}
// MARK: - VPNComet
func vpnLog(type: String, error: Error) { }
func vpnEvent(type: String, message: String, secured: String?) { }
func vpnEvent(name: String, attributes: [String: Any]?, secured: [String: Any]?) {
guard self.isActive else { return }
guard name.hasPrefix(PrivadoConstants.Event.Statistic.prefix),
let attributes = attributes else { return }
switch name {
case PrivadoConstants.Event.Statistic.VPN.connect:
self.track(connectEvent: "ConnectTrackEvent", attributes: attributes)
case PrivadoConstants.Event.Statistic.VPN.disconnect:
self.track(connectEvent: "DisconnectEvent", attributes: attributes)
case PrivadoConstants.Event.Statistic.VPN.reconnect:
self.track(connectEvent: "ReconnectEvent", attributes: attributes)
case PrivadoConstants.Event.Statistic.VPN.errorConnection:
self.track(connectEvent: "ErrorConnectEvent", attributes: attributes)
default:
break
}
}
// MARK: - Private
private func track(applicationEvent: String, attributes: [String: Any]) {
let params: [String: Any] = [
Constants.Param.name: applicationEvent,
Constants.Param.value: attributes[PrivadoConstants.Event.Attributes.value] ?? "",
Constants.Param.extradata: attributes[PrivadoConstants.Event.Attributes.extradata] ?? ""
]
Self.track(schema: Constants.Schema.application, data: params, using: self.tracker)
}
private func track(accountEvent: String, attributes: [String: Any]) {
guard let value = attributes[PrivadoConstants.Event.Attributes.success] as? Bool else { return }
let params: [String: Any] = [
Constants.Param.name: accountEvent,
Constants.Param.value: value ? "success" : "failure",
Constants.Param.extradata: ""
]
Self.track(schema: Constants.Schema.account, data: params, using: self.tracker)
}
private func track(connectEvent: String, attributes: [String: Any]) {
let params: [String: Any] = [
Constants.Param.name: connectEvent,
Constants.Param.vpnlocation: attributes[PrivadoConstants.Event.Attributes.city] ?? "",
Constants.Param.vpnserver: attributes[PrivadoConstants.Event.Attributes.server] ?? "",
Constants.Param.vpnprotocol: attributes[PrivadoConstants.Event.Attributes.proto] ?? "",
Constants.Param.extradata: attributes[PrivadoConstants.Event.Attributes.value] ?? ""
]
Self.track(schema: Constants.Schema.connection, data: params, using: self.tracker)
}
// MARK: - Static
private static func track(schema: String, data: [String: Any], using tracker: TrackerController) {
var params = data
params[Constants.Param.appversion] = Environment.shortVersion
params[Constants.Param.timestamp] = Self.dateFormatter.string(from: Date())
guard let selfDescribing = SelfDescribingJson(schema: schema, andDictionary: params) else {
return
}
let event = SelfDescribing(eventData: selfDescribing)
tracker.track(event)
}
}