diff --git a/glean-core/ios/Glean/Glean.swift b/glean-core/ios/Glean/Glean.swift index 55ff7ee002..9271faa3c1 100644 --- a/glean-core/ios/Glean/Glean.swift +++ b/glean-core/ios/Glean/Glean.swift @@ -122,6 +122,18 @@ public class Glean { // Check for overdue metrics pings self.metricsPingScheduler.schedule() + // Check if the "dirty flag" is set. That means the product was probably + // force-closed. If that's the case, submit a 'baseline' ping with the + // reason "dirty_startup". We only do that from the second run. + if !isFirstRun { + if glean_is_dirty_flag_set().toBool() { + self.submitPingByNameSync( + pingName: "baseline", + reason: "dirty_startup" + ) + } + } + // From the second time we run, after all startup pings are generated, // make sure to clear `lifetime: application` metrics and set them again. // Any new value will be sent in newly generted pings after startup. @@ -136,18 +148,6 @@ public class Glean { // Signal Dispatcher that init is complete Dispatchers.shared.flushQueuedInitialTasks() - // Check if the "dirty flag" is set. That means the product was probably - // force-closed. If that's the case, submit a 'baseline' ping with the - // reason "dirty_startup". We only do that from the second run. - if !isFirstRun { - if glean_is_dirty_flag_set().toBool() { - self.submitPingByNameSync( - pingName: "baseline", - reason: "dirty_startup" - ) - } - } - self.observer = GleanLifecycleObserver() if !uploadEnabled { diff --git a/glean-core/ios/GleanTests/GleanTests.swift b/glean-core/ios/GleanTests/GleanTests.swift index 655c55a040..58237de343 100644 --- a/glean-core/ios/GleanTests/GleanTests.swift +++ b/glean-core/ios/GleanTests/GleanTests.swift @@ -227,4 +227,60 @@ class GleanTests: XCTestCase { XCTAssertNil(error, "Test timed out waiting for upload: \(error!)") } } + + func testSendingOfStartupBaselinePingWithAppLifetimeMetric() { + // Set the dirty flag. + glean_set_dirty_flag(true.toByte()) + + let stringMetric = StringMetricType( + category: "telemetry", + name: "app_lifetime", + sendInPings: ["baseline"], + lifetime: .application, + disabled: false + ) + stringMetric.set("HELLOOOOO!") + + // Set up the test stub based on the default telemetry endpoint + let host = URL(string: Configuration.Constants.defaultTelemetryEndpoint)!.host! + stub(condition: isHost(host)) { data in + let path = (data as NSURLRequest).url! + let parts = path.absoluteString.split(separator: "/") + XCTAssertEqual("baseline", parts[4]) + + let body = (data as NSURLRequest).ohhttpStubs_HTTPBody() + let json = try! JSONSerialization.jsonObject(with: body!, options: []) as? [String: Any] + XCTAssert(json != nil) + + // Check for the "dirty_startup" flag + let pingInfo = json?["ping_info"] as? [String: Any] + XCTAssertEqual("dirty_startup", pingInfo?["reason"] as? String) + + // Ensure there is only the expected locale string metric + let metrics = json?["metrics"] as? [String: Any] + let strings = metrics?["string"] as? [String: Any] + let metric = strings?["telemetry.app_lifetime"] as? String + XCTAssertEqual("HELLOOOOO!", metric) + + DispatchQueue.main.async { + // let the response get processed before we mark the expectation fulfilled + self.expectation?.fulfill() + } + + return OHHTTPStubsResponse( + jsonObject: [], + statusCode: 200, + headers: ["Content-Type": "application/json"] + ) + } + + expectation = expectation(description: "baseline ping received") + + // Restart glean and don't clear the stores. + // This should trigger a baseline ping with a "dirty_startup" reason. + Glean.shared.resetGlean(clearStores: false) + waitForExpectations(timeout: 5.0) { error in + XCTAssertNil(error, "Test timed out waiting for upload: \(error!)") + } + } }