Skip to content

Commit

Permalink
feat: Context plugin (#8)
Browse files Browse the repository at this point in the history
* fix: contextplugin init

* fix: fix device model for macos

* fix: fix watchOS method type

Co-authored-by: Alyssa.Yu <alyssa.yu@AlyssaYus-MacBook-Pro.local>
  • Loading branch information
yuhao900914 and Alyssa.Yu authored Nov 23, 2022
1 parent 8405b62 commit 64ba783
Show file tree
Hide file tree
Showing 12 changed files with 573 additions and 30 deletions.
2 changes: 2 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
disabled_rules:
- function_body_length
- trailing_comma
- todo
identifier_name:
allowed_symbols: "_"
min_length: 1
cyclomatic_complexity: 25
2 changes: 1 addition & 1 deletion Sources/Amplitude/Configuration.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// File.swift
// Configuration.swift
//
//
// Created by Marvin Liu on 10/27/22.
Expand Down
20 changes: 19 additions & 1 deletion Sources/Amplitude/Constants.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// File.swift
// Constants.swift
//
//
// Created by Marvin Liu on 10/27/22.
Expand All @@ -22,6 +22,7 @@ enum ServerZone: String {

public struct Constants {
static let SDK_LIBRARY = "amplitude-swift"
static let SDK_VERSION = "0.0.0" // TODO: SHOULD IMPLEMENT THE SEMENTIC RELEASE TO AUTO UPDATE THIS VALUE
static let DEFAULT_API_HOST = "https://api2.amplitude.com/2/httpapi"
static let EU_DEFAULT_API_HOST = "https://api.eu.amplitude.com/2/httpapi"
static let BATCH_API_HOST = "https://api2.amplitude.com/batch"
Expand All @@ -32,6 +33,23 @@ public struct Constants {
static let MAX_PROPERTY_KEYS = 1024
static let MAX_STRING_LENGTH = 1024

static let AMP_TRACKING_OPTION_CARRIER = "carrier"
static let AMP_TRACKING_OPTION_CITY = "city"
static let AMP_TRACKING_OPTION_COUNTRY = "country"
static let AMP_TRACKING_OPTION_DEVICE_MANUFACTURER = "device_manufacturer"
static let AMP_TRACKING_OPTION_DEVICE_MODEL = "device_model"
static let AMP_TRACKING_OPTION_DMA = "dma"
static let AMP_TRACKING_OPTION_IDFA = "idfa"
static let AMP_TRACKING_OPTION_IDFV = "idfv"
static let AMP_TRACKING_OPTION_IP_ADDRESS = "ip_address"
static let AMP_TRACKING_OPTION_LANGUAGE = "language"
static let AMP_TRACKING_OPTION_LAT_LNG = "lat_lng"
static let AMP_TRACKING_OPTION_OS_NAME = "os_name"
static let AMP_TRACKING_OPTION_OS_VERSION = "os_version"
static let AMP_TRACKING_OPTION_PLATFORM = "platform"
static let AMP_TRACKING_OPTION_REGION = "region"
static let AMP_TRACKING_OPTION_VERSION_NAME = "version_name"

struct Configuration {
static let FLUSH_QUEUE_SIZE = 30
static let FLUSH_INTERVAL_MILLIS = 30 * 1000 // 30s
Expand Down
4 changes: 2 additions & 2 deletions Sources/Amplitude/Plugins/AmplitudeDestinationPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

public class AmplitudeDestinationPlugin: DestinationPlugin {
public let timeline = Timeline()
public var amplitude: Amplitude? = nil
public var amplitude: Amplitude?
public let type: PluginType = .destination
private var pipeline: EventPipeline?

Expand Down Expand Up @@ -54,7 +54,7 @@ public class AmplitudeDestinationPlugin: DestinationPlugin {
add(plugin: IdentityEventSender())
}

public func execute(event: BaseEvent) -> BaseEvent? {
public func execute(event: BaseEvent?) -> BaseEvent? {
return event
}
}
150 changes: 145 additions & 5 deletions Sources/Amplitude/Plugins/ContextPlugin.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// File.swift
// ContextPlugin.swift
//
//
// Created by Marvin Liu on 10/28/22.
Expand All @@ -9,13 +9,153 @@ import Foundation

class ContextPlugin: Plugin {
var type: PluginType = PluginType.before
public weak var amplitude: Amplitude?
internal static var device = VendorSystem.current

var amplitude: Amplitude?
func execute(event: BaseEvent?) -> BaseEvent? {
guard let workingEvent = event else { return event }

func setup(amplitude: Amplitude) {
let context = staticContext

// merge context data
mergeContext(event: workingEvent, context: context)

return workingEvent
}

internal var staticContext = staticContextData()

internal static func staticContextData() -> [String: Any] {
var staticContext = [String: Any]()
// library
staticContext["library"] = "\(Constants.SDK_LIBRARY)/\(Constants.SDK_VERSION)"

// app info
let info = Bundle.main.infoDictionary
let localizedInfo = Bundle.main.localizedInfoDictionary
var app = [String: Any]()
if let info = info {
app.merge(info) { (_, new) in new }
}

if let localizedInfo = localizedInfo {
app.merge(localizedInfo) { (_, new) in new }
}

if app.count != 0 {
staticContext["version_name"] = app["CFBundleShortVersionString"] ?? ""
}

// platform/device info
let device = self.device
staticContext["device_manufacturer"] = device.manufacturer
staticContext["device_model"] = device.model
staticContext["vendorID"] = device.identifierForVendor
staticContext["os_name"] = device.os_name
staticContext["os_version"] = device.os_version
staticContext["platform"] = device.platform
if Locale.preferredLanguages.count > 0 {
staticContext["language"] = Locale.preferredLanguages[0]
}

// TODO: need to add logic for multi carrier
/* let networkInfo = NSClassFromString("CTTelephonyNetworkInfo")
if networkInfo != nil {
let subscriberCellularProvider = NSSelectorFromString("subscriberCellularProvider")
let carrier = networkInfo?.method(for: subscriberCellularProvider) ?? "unknown"
staticContext["carrier"] = carrier
}
*/

if Locale.preferredLanguages.count > 0 {
staticContext["country"] = Locale.current.regionCode
}

return staticContext
}

func execute(event: BaseEvent) -> BaseEvent? {
return event
internal func mergeContext(event: BaseEvent, context: [String: Any]) {
if event.timestamp == nil {
event.timestamp = NSDate().timeIntervalSince1970 * 1000
}
if event.insertId == nil {
event.insertId = NSUUID().uuidString
}
if event.library == nil {
event.library = context["library"] as? String
}
if event.userId == nil {
// TODO: get stored userId
// event.userId = self.amplitude.store.userId
}
if event.deviceId == nil {
// TODO: get stored deviceID
// event.deviceId = self.amplitude.store.deviceId
}
if event.partnerId == nil {
if let pId = self.amplitude?.configuration.partnerId {
event.partnerId = pId
}
}
if event.ip == nil {
// get the ip in server side if there is no event level ip
event.ip = "$remote"
}
let configuration = self.amplitude?.configuration
let trackingOptions = configuration?.trackingOptions

if configuration?.enableCoppaControl ?? false {
trackingOptions?.mergeIn(other: TrackingOptions().forCoppaControl())
}

if trackingOptions?.shouldTrackVersionName() ?? false {
event.versionName = context["version_name"] as? String
}
if trackingOptions?.shouldTrackOsName() ?? false {
event.osName = context["os_name"] as? String
}
if trackingOptions?.shouldTrackOsVersion() ?? false {
event.osVersion = context["os_version"] as? String
}
if trackingOptions?.shouldTrackDeviceManufacturer() ?? false {
event.deviceManufacturer = context["device_manufacturer"] as? String
}
if trackingOptions?.shouldTrackDeviceModel() ?? false {
event.deviceModel = context["device_model"] as? String
}
if trackingOptions?.shouldTrackCarrier() ?? false {
event.carrier = context["carrier"] as? String
}
if trackingOptions?.shouldTrackIpAddress() ?? false {
guard event.ip != nil else {
event.ip = "$remote"
return
}
}
if trackingOptions?.shouldTrackCountry() ?? false && event.ip != "$remote" {
event.country = context["country"] as? String
}
// TODO: get lat and lng from locationInfoBlock
/*if (trackingOptions?.shouldTrackLatLng() ?? false) && (self.amplitude.locationInfoBlock != nil) {
let location = self.amplitude.locationInfoBlock();
event.locationLat = location.lat
event.locationLng = location.lng
}*/
if trackingOptions?.shouldTrackLanguage() ?? false {
event.language = context["language"] as? String
}
if trackingOptions?.shouldTrackPlatform() ?? false {
event.platform = context["platform"] as? String
}
if event.plan == nil {
if let plan = self.amplitude?.configuration.plan {
event.plan = plan
}
}
if event.ingestionMetadata == nil {
if let ingestionMetadata = self.amplitude?.configuration.ingestionMetadata {
event.ingestionMetadata = ingestionMetadata
}
}
}
}
2 changes: 1 addition & 1 deletion Sources/Amplitude/Plugins/IdentityEventSender.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal class IdentityEventSender: Plugin {

}

func execute(event: BaseEvent) -> BaseEvent? {
func execute(event: BaseEvent?) -> BaseEvent? {
return event
}
}
Loading

0 comments on commit 64ba783

Please sign in to comment.