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

fix(analytics): Re-add option to track lifecyle events #2788

Merged
Merged
Show file tree
Hide file tree
Changes from 7 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
9 changes: 7 additions & 2 deletions aws-analytics-pinpoint/api/aws-analytics-pinpoint.api
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,23 @@ public final class com/amplifyframework/analytics/pinpoint/AWSPinpointAnalyticsP
public static final field Companion Lcom/amplifyframework/analytics/pinpoint/AWSPinpointAnalyticsPlugin$Options$Companion;
public static final fun builder ()Lcom/amplifyframework/analytics/pinpoint/AWSPinpointAnalyticsPlugin$Options$Builder;
public final fun component1 ()J
public final fun copy (J)Lcom/amplifyframework/analytics/pinpoint/AWSPinpointAnalyticsPlugin$Options;
public static synthetic fun copy$default (Lcom/amplifyframework/analytics/pinpoint/AWSPinpointAnalyticsPlugin$Options;JILjava/lang/Object;)Lcom/amplifyframework/analytics/pinpoint/AWSPinpointAnalyticsPlugin$Options;
public final fun component2 ()Z
public final fun copy (JZ)Lcom/amplifyframework/analytics/pinpoint/AWSPinpointAnalyticsPlugin$Options;
public static synthetic fun copy$default (Lcom/amplifyframework/analytics/pinpoint/AWSPinpointAnalyticsPlugin$Options;JZILjava/lang/Object;)Lcom/amplifyframework/analytics/pinpoint/AWSPinpointAnalyticsPlugin$Options;
public fun equals (Ljava/lang/Object;)Z
public final fun getAutoFlushEventsInterval ()J
public final fun getTrackLifecycleEvents ()Z
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class com/amplifyframework/analytics/pinpoint/AWSPinpointAnalyticsPlugin$Options$Builder {
public final fun autoFlushEventsInterval (J)Lcom/amplifyframework/analytics/pinpoint/AWSPinpointAnalyticsPlugin$Options$Builder;
public final fun getAutoFlushEventsInterval ()J
public final fun getTrackLifecycleEvents ()Z
public final synthetic fun setAutoFlushEventsInterval (J)V
public final synthetic fun setTrackLifecycleEvents (Z)V
public final fun trackLifecycleEvents (Z)Lcom/amplifyframework/analytics/pinpoint/AWSPinpointAnalyticsPlugin$Options$Builder;
}

public final class com/amplifyframework/analytics/pinpoint/AWSPinpointAnalyticsPlugin$Options$Companion {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,20 @@ class AWSPinpointAnalyticsPlugin @JvmOverloads constructor(
// amplifyconfiguration file
if (userOptions != null) {
configBuilder.withAutoFlushEventsInterval(userOptions.autoFlushEventsInterval)
} else if (pinpointAnalyticsConfigJson.has(PinpointConfigurationKey.AUTO_FLUSH_INTERVAL.configurationKey)) {
configBuilder.withAutoFlushEventsInterval(
pinpointAnalyticsConfigJson.getLong(PinpointConfigurationKey.AUTO_FLUSH_INTERVAL.configurationKey)
)
.withTrackAppLifecycleEvents(userOptions.trackLifecycleEvents)
} else {
if (pinpointAnalyticsConfigJson.has(PinpointConfigurationKey.AUTO_FLUSH_INTERVAL.configurationKey)) {
configBuilder.withAutoFlushEventsInterval(
pinpointAnalyticsConfigJson.getLong(PinpointConfigurationKey.AUTO_FLUSH_INTERVAL.configurationKey)
)
}
if (pinpointAnalyticsConfigJson.has(PinpointConfigurationKey.TRACK_APP_LIFECYCLE_EVENTS.configurationKey)) {
configBuilder.withTrackAppLifecycleEvents(
pinpointAnalyticsConfigJson.getBoolean(
PinpointConfigurationKey.TRACK_APP_LIFECYCLE_EVENTS.configurationKey
)
)
}
}
val awsAnalyticsConfig = configBuilder.build()
configure(awsAnalyticsConfig, context)
Expand Down Expand Up @@ -132,7 +142,12 @@ class AWSPinpointAnalyticsPlugin @JvmOverloads constructor(
/**
* The interval between sends of queued analytics events, in milliseconds
*/
val autoFlushEventsInterval: Long
val autoFlushEventsInterval: Long,

/**
* If true then the plugin will stop sessions when the app goes to the background
*/
val trackLifecycleEvents: Boolean
) {
companion object {
/**
Expand All @@ -155,17 +170,28 @@ class AWSPinpointAnalyticsPlugin @JvmOverloads constructor(
*/
class Builder internal constructor() {
/**
* Set the interval between sends of queed analytics events, in milliseconds
* Set the interval between sends of queued analytics events, in milliseconds
*/
var autoFlushEventsInterval: Long = AWSPinpointAnalyticsPluginConfiguration.DEFAULT_AUTO_FLUSH_INTERVAL
@JvmSynthetic set

/**
* Set whether or not the plugin will stop/start sessions when the app goes to the background/foreground.
*/
var trackLifecycleEvents: Boolean = true
@JvmSynthetic set

/**
* Set the interval between sends of queed analytics events, in milliseconds
*/
fun autoFlushEventsInterval(value: Long) = apply { autoFlushEventsInterval = value }

internal fun build() = Options(autoFlushEventsInterval = autoFlushEventsInterval)
fun trackLifecycleEvents(value: Boolean) = apply { trackLifecycleEvents = value }

internal fun build() = Options(
autoFlushEventsInterval = autoFlushEventsInterval,
trackLifecycleEvents = trackLifecycleEvents
)
}
}
}
Expand All @@ -189,5 +215,10 @@ private enum class PinpointConfigurationKey(
/**
* Time interval after which the events are automatically submitted to pinpoint.
*/
AUTO_FLUSH_INTERVAL("autoFlushEventsInterval")
AUTO_FLUSH_INTERVAL("autoFlushEventsInterval"),

/**
* Whether to track app lifecycle events automatically.
*/
TRACK_APP_LIFECYCLE_EVENTS("trackAppLifecycleEvents")
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ final class AWSPinpointAnalyticsPluginConfiguration {
private final String appId;
private final String region;
private final long autoFlushEventsInterval;
private final boolean trackAppLifecycleEvents;

private AWSPinpointAnalyticsPluginConfiguration(Builder builder) {
this.appId = builder.appId;
this.region = builder.region;
this.autoFlushEventsInterval = builder.autoFlushEventsInterval;
this.trackAppLifecycleEvents = builder.trackAppLifecycleEvents;
}

/**
Expand Down Expand Up @@ -67,6 +69,14 @@ long getAutoFlushEventsInterval() {
return autoFlushEventsInterval;
}

/**
* Is auto session tracking enabled.
* @return Is auto session tracking enabled.
*/
boolean isTrackAppLifecycleEvents() {
return trackAppLifecycleEvents;
}

/**
* Return a builder that can be used to construct a new instance of
* {@link AWSPinpointAnalyticsPluginConfiguration}.
Expand Down Expand Up @@ -95,6 +105,7 @@ static AWSPinpointAnalyticsPluginConfiguration from(
.withAppId(analytics.getAmazonPinpoint().getAppId())
.withRegion(analytics.getAmazonPinpoint().getAwsRegion())
.withAutoFlushEventsInterval(options.getAutoFlushEventsInterval())
.withTrackAppLifecycleEvents(options.getTrackLifecycleEvents())
.build();
}

Expand All @@ -105,6 +116,7 @@ static final class Builder {
private String appId;
private String region;
private long autoFlushEventsInterval = DEFAULT_AUTO_FLUSH_INTERVAL;
private boolean trackAppLifecycleEvents = true;

Builder withAppId(final String appId) {
this.appId = appId;
Expand All @@ -116,6 +128,11 @@ Builder withRegion(final String region) {
return this;
}

Builder withTrackAppLifecycleEvents(final boolean trackAppLifecycleEvents) {
this.trackAppLifecycleEvents = trackAppLifecycleEvents;
return this;
}

Builder withAutoFlushEventsInterval(final long autoFlushEventsInterval) {
this.autoFlushEventsInterval = autoFlushEventsInterval;
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,18 @@ internal class PinpointManager constructor(
encryptedStore,
sharedPrefs,
androidAppDetails,
androidDeviceDetails,
androidDeviceDetails
)
analyticsClient = AnalyticsClient(
context,
awsPinpointConfiguration.autoFlushEventsInterval,
awsPinpointConfiguration.isTrackAppLifecycleEvents,
pinpointClient,
targetingClient,
pinpointDatabase,
sharedPrefs.getUniqueId(),
androidAppDetails,
androidDeviceDetails,
androidDeviceDetails
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package com.amplifyframework.analytics.pinpoint

import com.amplifyframework.testutils.configuration.amplifyOutputsData
import io.kotest.matchers.booleans.shouldBeTrue
import io.kotest.matchers.shouldBe
import org.junit.Test

Expand All @@ -33,12 +34,26 @@ class AWSPinpointAnalyticsPluginConfigurationTest {
}
val options = AWSPinpointAnalyticsPlugin.Options {
autoFlushEventsInterval = 42
trackLifecycleEvents = false
}

val configuration = AWSPinpointAnalyticsPluginConfiguration.from(outputs, options)

configuration.appId shouldBe "test-app"
configuration.region shouldBe "test-region"
configuration.autoFlushEventsInterval shouldBe 42
configuration.isTrackAppLifecycleEvents shouldBe false
}

@Test
fun `default auto flush interval is 30 seconds`() {
val configuration = AWSPinpointAnalyticsPluginConfiguration.builder().build()
configuration.autoFlushEventsInterval shouldBe 30_000
}

@Test
fun `default track lifecycle events is true`() {
val configuration = AWSPinpointAnalyticsPluginConfiguration.builder().build()
configuration.isTrackAppLifecycleEvents.shouldBeTrue()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

package com.amplifyframework.analytics.pinpoint

import io.kotest.matchers.booleans.shouldBeTrue
import io.kotest.matchers.shouldBe
import org.junit.Test

Expand All @@ -26,4 +27,10 @@ class OptionsTest {

options.autoFlushEventsInterval shouldBe configuration.autoFlushEventsInterval
}

@Test
fun `default track lifecycle events is true`() {
val options = AWSPinpointAnalyticsPlugin.Options.defaults()
options.trackLifecycleEvents.shouldBeTrue()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package com.amplifyframework.pinpoint.core

import android.app.Application
import android.content.Context
import androidx.annotation.VisibleForTesting
import aws.sdk.kotlin.services.pinpoint.PinpointClient
import com.amplifyframework.analytics.AnalyticsChannelEventName
import com.amplifyframework.annotations.InternalAmplifyApi
Expand All @@ -42,6 +43,7 @@ import kotlinx.coroutines.launch
class AnalyticsClient(
val context: Context,
autoFlushEventsInterval: Long,
trackLifecycleEvents: Boolean,
pinpointClient: PinpointClient,
targetingClient: TargetingClient,
pinpointDatabase: PinpointDatabase,
Expand All @@ -68,7 +70,12 @@ class AnalyticsClient(
private val globalMetrics = ConcurrentHashMap<String, Double>()

private val autoEventSubmitter = AutoEventSubmitter(this, autoFlushEventsInterval)
private val autoSessionTracker = sessionClient?.let { AutoSessionTracker(this, it) }

@VisibleForTesting val autoSessionTracker = if (trackLifecycleEvents) {
sessionClient?.let { AutoSessionTracker(this, it) }
} else {
null
}

init {
sessionClient?.let {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import com.amplifyframework.pinpoint.core.models.PinpointEvent
import com.amplifyframework.pinpoint.core.models.PinpointSession
import com.amplifyframework.pinpoint.core.models.SDKInfo
import com.amplifyframework.pinpoint.core.util.getUniqueId
import io.kotest.matchers.nulls.shouldBeNull
import io.kotest.matchers.nulls.shouldNotBeNull
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
Expand Down Expand Up @@ -67,6 +69,7 @@ class AnalyticsClientTest {
analyticsClient = AnalyticsClient(
ApplicationProvider.getApplicationContext(),
30000L,
true,
pinpointClient,
targetingClient,
pinpointDatabase,
Expand Down Expand Up @@ -161,6 +164,48 @@ class AnalyticsClientTest {
assertEquals(metricValue, analyticsClient.getGlobalMetrics()[metricName])
}

@Test
fun `auto tracker is null if trackLifecycleEvents is false`() {
val client = AnalyticsClient(
ApplicationProvider.getApplicationContext(),
30000L,
false,
pinpointClient,
targetingClient,
pinpointDatabase,
sharedPrefs.getUniqueId(),
androidAppDetails,
androidDeviceDetails,
sessionClient,
UnconfinedTestDispatcher(),
sdkInfo,
eventRecorder
)

client.autoSessionTracker.shouldBeNull()
}

@Test
fun `auto tracker is not null if trackLifecycleEvents is true`() {
val client = AnalyticsClient(
ApplicationProvider.getApplicationContext(),
30000L,
true,
pinpointClient,
targetingClient,
pinpointDatabase,
sharedPrefs.getUniqueId(),
androidAppDetails,
androidDeviceDetails,
sessionClient,
UnconfinedTestDispatcher(),
sdkInfo,
eventRecorder
)

client.autoSessionTracker.shouldNotBeNull()
}

@After
fun tearDown() {
analyticsClient.disableEventSubmitter()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class AWSPinpointPushNotificationsPlugin : PushNotificationsPlugin<PinpointClien

private const val DATABASE_NAME = "awspushnotifications.db"
private const val DEFAULT_AUTO_FLUSH_INTERVAL = 30000L
private const val DEFAULT_TRACK_LIFECYCLE_EVENTS = true
private const val AWS_PINPOINT_PUSHNOTIFICATIONS_PREFERENCES_SUFFIX = "515d6767-01b7-49e5-8273-c8d11b0f331d"
private const val AWS_PINPOINT_PUSHNOTIFICATIONS_DEVICE_TOKEN_LEGACY_KEY = "AWSPINPOINT.GCMTOKEN"
}
Expand Down Expand Up @@ -164,6 +165,7 @@ class AWSPinpointPushNotificationsPlugin : PushNotificationsPlugin<PinpointClien
return AnalyticsClient(
context,
DEFAULT_AUTO_FLUSH_INTERVAL,
DEFAULT_TRACK_LIFECYCLE_EVENTS,
pinpointClient,
targetingClient,
pinpointDatabase,
Expand Down