44
55package mozilla.components.service.glean
66
7- import android.arch.lifecycle.ProcessLifecycleOwner
87import android.content.Context
98import android.content.pm.PackageManager
109import android.support.annotation.VisibleForTesting
11- import kotlinx.coroutines.Dispatchers
12- import kotlinx.coroutines.GlobalScope
13- import kotlinx.coroutines.launch
14-
15- import java.util.UUID
1610
1711import mozilla.components.service.glean.config.Configuration
1812import mozilla.components.service.glean.firstrun.FileFirstRunDetector
1913import mozilla.components.service.glean.GleanMetrics.GleanInternalMetrics
20- import mozilla.components.service.glean.net.HttpPingUploader
21- import mozilla.components.service.glean.ping.PingMaker
22- import mozilla.components.service.glean.scheduler.GleanLifecycleObserver
14+ import mozilla.components.service.glean.scheduler.PingScheduler
2315import mozilla.components.service.glean.storages.ExperimentsStorageEngine
2416import mozilla.components.service.glean.storages.StorageEngineManager
2517import mozilla.components.service.glean.ping.BaselinePing
26- import mozilla.components.service.glean.scheduler.MetricsPingScheduler
2718import mozilla.components.service.glean.storages.StringsStorageEngine
2819import mozilla.components.service.glean.storages.UuidsStorageEngine
2920import mozilla.components.support.base.log.logger.Logger
3021import java.io.File
22+ import java.util.UUID
3123
32- @Suppress(" TooManyFunctions" )
3324open class GleanInternalAPI internal constructor () {
3425 private val logger = Logger (" glean/Glean" )
3526
36- // Include our singletons of StorageEngineManager and PingMaker
3727 private lateinit var storageEngineManager: StorageEngineManager
38- private lateinit var pingMaker: PingMaker
3928 internal lateinit var configuration: Configuration
4029
41- // `internal` so this can be modified for testing
42- internal lateinit var httpPingUploader: HttpPingUploader
43-
44- private val gleanLifecycleObserver by lazy { GleanLifecycleObserver () }
30+ internal lateinit var pingScheduler: PingScheduler
4531
4632 // `internal` so this can be modified for testing
4733 internal var initialized = false
4834 private var uploadEnabled = true
4935
50- // The application id detected by glean to be used as part of the submission
51- // endpoint.
52- internal lateinit var applicationId: String
53-
54- // This object holds data related to any persistent information about the metrics ping,
55- // such as the last time it was sent and the store name
56- internal lateinit var metricsPingScheduler: MetricsPingScheduler
57-
5836 // This object encapsulates initialization and information related to the baseline ping
5937 internal lateinit var baselinePing: BaselinePing
6038
@@ -63,10 +41,10 @@ open class GleanInternalAPI internal constructor () {
6341 *
6442 * This should only be initialized once by the application, and not by
6543 * libraries using glean. A message is logged to error and no changes are made
66- * to the state if initialize is called a more than once.
44+ * to the state if initialize is called more than once.
6745 *
68- * A LifecycleObserver will be added to send pings when the application goes
69- * into the background.
46+ * A [PingScheduler] will be added as a [LifecycleObserver] to schedule pings when the
47+ * application goes into the background.
7048 *
7149 * @param applicationContext [Context] to access application features, such
7250 * as shared preferences
@@ -82,15 +60,12 @@ open class GleanInternalAPI internal constructor () {
8260 }
8361
8462 storageEngineManager = StorageEngineManager (applicationContext = applicationContext)
85- pingMaker = PingMaker (storageEngineManager, applicationContext )
63+ pingScheduler = PingScheduler (applicationContext, storageEngineManager )
8664 this .configuration = configuration
87- httpPingUploader = HttpPingUploader ()
88- initialized = true
89- applicationId = sanitizeApplicationId(applicationContext.packageName)
9065
9166 initializeCoreMetrics(applicationContext)
9267
93- ProcessLifecycleOwner .get().lifecycle.addObserver(gleanLifecycleObserver)
68+ initialized = true
9469 }
9570
9671 /* *
@@ -154,40 +129,6 @@ open class GleanInternalAPI internal constructor () {
154129 ExperimentsStorageEngine .clearAllStores()
155130 }
156131
157- @VisibleForTesting(otherwise = VisibleForTesting .PRIVATE )
158- internal fun makePath (docType : String , uuid : UUID ): String {
159- return " /submit/$applicationId /$docType /${Glean .SCHEMA_VERSION } /$uuid "
160- }
161-
162- /* *
163- * Collect and assemble the ping. Asynchronously submits the assembled
164- * payload to the designated server using [httpPingUploader] but only
165- * if upload is enabled, and there is ping data to send.
166- */
167- internal fun sendPing (store : String , docType : String ) {
168- if (! isInitialized()) {
169- logger.error(" Attempted to send ping before Glean was initialized." )
170- return
171- }
172-
173- // Do not send ping if upload is disabled
174- if (! getUploadEnabled()) {
175- logger.debug(" Attempt to send ping \" $store \" but metrics disabled, aborting send." )
176- return
177- }
178-
179- // Build and send the ping on an async thread. Since the pingMaker.collect() function
180- // returns null if there is nothing to send we can use this to avoid sending an empty ping
181- pingMaker.collect(store)?.let { pingContent ->
182- val uuid = UUID .randomUUID()
183- val path = makePath(docType, uuid)
184- // Asynchronously perform the HTTP upload off the main thread.
185- GlobalScope .launch(Dispatchers .IO ) {
186- httpPingUploader.upload(path = path, data = pingContent, config = configuration)
187- }
188- }
189- }
190-
191132 /* *
192133 * Initialize the core metrics internally managed by Glean (e.g. client id).
193134 */
@@ -238,52 +179,16 @@ open class GleanInternalAPI internal constructor () {
238179 throw AssertionError (" Could not get own package info, aborting init" )
239180 }
240181
241- // Set up information and scheduling for glean owned pings
242- metricsPingScheduler = MetricsPingScheduler (applicationContext)
182+ // Create a baseline ping to initialize the associated metrics
243183 baselinePing = BaselinePing (applicationContext)
244184 }
245185
246186 /* *
247- * Sanitizes the application id, generating a pipeline-friendly string that replaces
248- * non alphanumeric characters with dashes.
249- *
250- * @param applicationId the string representing the application id
251- *
252- * @return the sanitized version of the application id
187+ * Helper function to force scheduling of pings immediately. Note that the 'metrics' ping
188+ * schedule is still dependent on it's internal schedule of no more than once every 24 hours.
253189 */
254- internal fun sanitizeApplicationId (applicationId : String ): String {
255- return applicationId.replace(" [^a-zA-Z0-9]+" .toRegex(), " -" )
256- }
257-
258- /* *
259- * Handle an event and send the appropriate pings.
260- *
261- * Valid events are:
262- *
263- * - Background: When the application goes to the background.
264- * This triggers sending of the baseline ping.
265- * - Default: Event that triggers the default pings.
266- *
267- * @param pingEvent The type of the event.
268- */
269- fun handleEvent (pingEvent : Glean .PingEvent ) {
270- if (! isInitialized()) {
271- logger.error(" Glean must be initialized before handling events." )
272- return
273- }
274-
275- when (pingEvent) {
276- Glean .PingEvent .Background -> {
277- sendPing(BaselinePing .STORE_NAME , BaselinePing .STORE_NAME )
278- sendPing(" events" , " events" )
279- }
280- Glean .PingEvent .Default -> {
281- if (metricsPingScheduler.canSendPing()) {
282- sendPing(MetricsPingScheduler .STORE_NAME , MetricsPingScheduler .STORE_NAME )
283- metricsPingScheduler.updateSentTimestamp()
284- }
285- }
286- }
190+ fun schedulePingsNow () {
191+ pingScheduler.onEnterBackground()
287192 }
288193
289194 /* *
@@ -297,19 +202,6 @@ open class GleanInternalAPI internal constructor () {
297202}
298203
299204object Glean : GleanInternalAPI() {
300- /* *
301- * Enumeration of different metric lifetimes.
302- */
303- enum class PingEvent {
304- /* *
305- * When the application goes into the background
306- */
307- Background ,
308- /* *
309- * A periodic event to send the default ping
310- */
311- Default
312- }
313205
314206 internal const val SCHEMA_VERSION = 2
315207
0 commit comments