in glean-core/ios/Glean/Scheduler/MetricsPingScheduler.swift [117:179]
func schedule() -> Bool {
let now = Date()
// If the version of the app is different from the last time we ran the app,
// schedule the metrics ping for immediate collection. We only need to perform
// this check at startup (when overduePingAsFirst is true).
if isDifferentVersion() {
self.collectPingAndReschedule(
now,
startupPing: true,
reason: .upgrade
)
return true
}
let lastSentDate = getLastCollectedDate()
logger.debug("The 'metrics' ping was last sent on \(String(describing: lastSentDate))")
// We expect to cover 3 cases here:
//
// (1) - the ping was already collected on the current calendar day; only schedule
// one for collecting the next calendar day at the due time;
// (2) - the ping was NOT collected on the current calendar day, and we're later than
// the due time; collect the ping immediately;
// (3) - the ping was NOT collected on the current calendar day, but we still have
// some time to the due time; schedule for sending the current calendar day.
let alreadySentToday = lastSentDate != nil && Calendar.current.isDateInToday(lastSentDate!)
if alreadySentToday {
// The metrics ping was already sent today. Schedule it for the next
// calendar day. This addresses (1).
logger.info("The 'metrics' ping was already sent today, \(now).")
schedulePingCollection(
now,
sendTheNextCalendarDay: true,
reason: .tomorrow
)
return false
} else if isAfterDueTime(now) {
logger.info("The 'metrics' ping is scheduled for immediate collection, \(now)")
// **IMPORTANT**
//
// We want to make sure no other metric API adds data before the ping is collected.
// `schedule` should be called off of the main thread. As long as `schedule` is
// invoked before replaying any queued recording API call, it guarantees this step
// is completed before anything else is recorded.
self.collectPingAndReschedule(
now,
startupPing: true,
reason: .overdue
)
return true
} else {
// This covers (3).
logger.info("The 'metrics' collection is scheduled for today, \(now)")
schedulePingCollection(
now,
sendTheNextCalendarDay: false,
reason: .today
)
return false
}
}