Skip to content

Commit efa78d8

Browse files
authored
Merge 8102e0f into 8fe1383
2 parents 8fe1383 + 8102e0f commit efa78d8

File tree

5 files changed

+105
-35
lines changed

5 files changed

+105
-35
lines changed

firebase-perf/src/main/java/com/google/firebase/perf/FirebasePerfEarly.java

+1-5
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,8 @@ public FirebasePerfEarly(
5151
uiExecutor.execute(new AppStartTrace.StartFromBackgroundRunnable(appStartTrace));
5252
}
5353

54-
// TODO: Bring back Firebase Sessions dependency to watch for updates to sessions.
54+
// In the case of a cold start, we initialize gauge collection with a legacy PerfSession.
5555

56-
// In the case of cold start, we create a session and start collecting gauges as early as
57-
// possible.
58-
// There is code in SessionManager that prevents us from resetting the session twice in case
59-
// of app cold start.
6056
SessionManager.getInstance().initializeGaugeCollection();
6157
}
6258
}

firebase-perf/src/main/java/com/google/firebase/perf/session/FirebasePerformanceSessionSubscriber.kt

+8-1
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,19 @@ class FirebasePerformanceSessionSubscriber(override val isDataCollectionEnabled:
2828

2929
override fun onSessionChanged(sessionDetails: SessionSubscriber.SessionDetails) {
3030
val currentPerfSession = SessionManager.getInstance().perfSession()
31-
// TODO(b/394127311): Add logic to deal with app start gauges.
3231
FirebaseSessionsEnforcementCheck.checkSession(currentPerfSession, "onSessionChanged")
3332

33+
if (currentPerfSession.isLegacy() && currentPerfSession.isVerbose) {
34+
GaugeManager.getInstance()
35+
.logGaugeMetadata(sessionDetails.sessionId, ApplicationProcessState.FOREGROUND)
36+
GaugeManager.getInstance()
37+
.logExistingGaugeMetrics(sessionDetails.sessionId, ApplicationProcessState.FOREGROUND)
38+
}
39+
3440
val updatedSession = PerfSession.createWithId(sessionDetails.sessionId)
3541
SessionManager.getInstance().updatePerfSession(updatedSession)
3642
GaugeManager.getInstance()
3743
.logGaugeMetadata(updatedSession.sessionId(), ApplicationProcessState.FOREGROUND)
44+
SessionManager.getInstance().updateGaugeCollectionOnNewSession()
3845
}
3946
}

firebase-perf/src/main/java/com/google/firebase/perf/session/PerfSession.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
public class PerfSession implements Parcelable {
3131
private final Timer creationTime;
3232
private final String sessionId;
33-
private boolean isGaugeAndEventCollectionEnabled = false;
33+
private boolean isGaugeAndEventCollectionEnabled = true;
3434

3535
/*
3636
* Creates a PerfSession object and decides what metrics to collect.

firebase-perf/src/main/java/com/google/firebase/perf/session/SessionManager.java

+37-23
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,10 @@
1919
import androidx.annotation.Keep;
2020
import androidx.annotation.VisibleForTesting;
2121
import com.google.firebase.perf.application.AppStateMonitor;
22+
import com.google.firebase.perf.application.AppStateUpdateHandler;
2223
import com.google.firebase.perf.logging.FirebaseSessionsEnforcementCheck;
2324
import com.google.firebase.perf.session.gauges.GaugeManager;
2425
import com.google.firebase.perf.v1.ApplicationProcessState;
25-
import com.google.firebase.perf.v1.GaugeMetadata;
26-
import com.google.firebase.perf.v1.GaugeMetric;
2726
import java.lang.ref.WeakReference;
2827
import java.util.HashSet;
2928
import java.util.Iterator;
@@ -32,7 +31,7 @@
3231

3332
/** Session manager to generate sessionIDs and broadcast to the application. */
3433
@Keep // Needed because of b/117526359.
35-
public class SessionManager {
34+
public class SessionManager extends AppStateUpdateHandler {
3635
@SuppressLint("StaticFieldLeak")
3736
private static final SessionManager instance = new SessionManager();
3837

@@ -66,6 +65,7 @@ public SessionManager(
6665
this.gaugeManager = gaugeManager;
6766
this.perfSession = perfSession;
6867
this.appStateMonitor = appStateMonitor;
68+
registerForAppState();
6969
}
7070

7171
/**
@@ -76,6 +76,21 @@ public void setApplicationContext(final Context appContext) {
7676
gaugeManager.initializeGaugeMetadataManager(appContext);
7777
}
7878

79+
@Override
80+
public void onUpdateAppState(ApplicationProcessState newAppState) {
81+
super.onUpdateAppState(newAppState);
82+
if (appStateMonitor.isColdStart()) {
83+
// Ignore the app state change if it's a cold start.
84+
return;
85+
}
86+
87+
// TODO(b/394127311): Verify if this is called after a new session.
88+
if (this.perfSession.isVerbose()) {
89+
long collectionFrequency = updateGaugeCollection(newAppState);
90+
updateGaugeLogging(perfSession.sessionId(), newAppState, collectionFrequency);
91+
}
92+
}
93+
7994
/**
8095
* Checks if the current {@link PerfSession} is expired/timed out. If so, stop collecting gauges.
8196
*
@@ -92,12 +107,10 @@ public void stopGaugeCollectionIfSessionRunningTooLong() {
92107
}
93108

94109
/**
95-
* Updates the currently associated {@link #perfSession} and broadcast the change.
96-
*
97-
* <p>Uses the provided PerfSession {@link PerfSession}, log the {@link GaugeMetadata} and
98-
* start/stop the collection of {@link GaugeMetric} depending upon Session verbosity.
110+
* Updates the currently associated {@link #perfSession} and broadcast the change to relevant
111+
* traces.
99112
*
100-
* @see PerfSession#isVerbose()
113+
* <p>Uses the provided PerfSession {@link PerfSession}.
101114
*/
102115
public void updatePerfSession(PerfSession perfSession) {
103116
// Do not update the perf session if it is the exact same sessionId.
@@ -106,9 +119,6 @@ public void updatePerfSession(PerfSession perfSession) {
106119
}
107120

108121
this.perfSession = perfSession;
109-
110-
// TODO(b/394127311): Update/verify behavior for Firebase Sessions.
111-
112122
synchronized (clients) {
113123
for (Iterator<WeakReference<SessionAwareObject>> i = clients.iterator(); i.hasNext(); ) {
114124
SessionAwareObject callback = i.next().get();
@@ -121,9 +131,6 @@ public void updatePerfSession(PerfSession perfSession) {
121131
}
122132
}
123133
}
124-
125-
// Start of stop the gauge data collection.
126-
startOrStopCollectingGauges(appStateMonitor.getAppState());
127134
}
128135

129136
/**
@@ -133,7 +140,16 @@ public void updatePerfSession(PerfSession perfSession) {
133140
* this does not reset the perfSession.
134141
*/
135142
public void initializeGaugeCollection() {
136-
startOrStopCollectingGauges(ApplicationProcessState.FOREGROUND);
143+
if (perfSession.isVerbose()) {
144+
updateGaugeCollection(ApplicationProcessState.FOREGROUND);
145+
}
146+
}
147+
148+
public void updateGaugeCollectionOnNewSession() {
149+
if (perfSession.isVerbose()) {
150+
long frequency = updateGaugeCollection(ApplicationProcessState.FOREGROUND);
151+
updateGaugeLogging(perfSession.sessionId(), ApplicationProcessState.FOREGROUND, frequency);
152+
}
137153
}
138154

139155
/**
@@ -160,15 +176,13 @@ public void unregisterForSessionUpdates(WeakReference<SessionAwareObject> client
160176
}
161177
}
162178

163-
private void startOrStopCollectingGauges(ApplicationProcessState appState) {
164-
FirebaseSessionsEnforcementCheck.checkSession(
165-
perfSession, "Session is not ready while trying to startOrStopCollectingGauges");
179+
private long updateGaugeCollection(ApplicationProcessState applicationProcessState) {
180+
return gaugeManager.updateGaugeCollection(applicationProcessState, perfSession.getTimer());
181+
}
166182

167-
if (perfSession.isGaugeAndEventCollectionEnabled()) {
168-
gaugeManager.startCollectingGauges(perfSession, appState);
169-
} else {
170-
gaugeManager.stopCollectingGauges();
171-
}
183+
private void updateGaugeLogging(
184+
String sessionId, ApplicationProcessState applicationProcessState, long collectionFrequency) {
185+
gaugeManager.updateGaugeLogging(sessionId, applicationProcessState, collectionFrequency);
172186
}
173187

174188
@VisibleForTesting

firebase-perf/src/main/java/com/google/firebase/perf/session/gauges/GaugeManager.java

+58-5
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@ public class GaugeManager {
5959
private final TransportManager transportManager;
6060

6161
@Nullable private GaugeMetadataManager gaugeMetadataManager;
62-
@Nullable private ScheduledFuture gaugeManagerDataCollectionJob = null;
62+
@Nullable private ScheduledFuture<?> gaugeManagerDataCollectionJob = null;
6363
@Nullable private String sessionId = null;
64+
65+
private boolean isCollectingGauges = false;
6466
private ApplicationProcessState applicationProcessState =
6567
ApplicationProcessState.APPLICATION_PROCESS_STATE_UNKNOWN;
6668

@@ -103,6 +105,34 @@ public static synchronized GaugeManager getInstance() {
103105
return instance;
104106
}
105107

108+
public void updateGaugeLogging(
109+
String sessionId, ApplicationProcessState applicationProcessState, long collectionFrequency) {
110+
try {
111+
gaugeManagerDataCollectionJob =
112+
gaugeManagerExecutor
113+
.get()
114+
.scheduleWithFixedDelay(
115+
() -> {
116+
syncFlush(sessionId, applicationProcessState);
117+
},
118+
/* initialDelay= */ collectionFrequency
119+
* APPROX_NUMBER_OF_DATA_POINTS_PER_GAUGE_METRIC,
120+
/* period= */ collectionFrequency * APPROX_NUMBER_OF_DATA_POINTS_PER_GAUGE_METRIC,
121+
TimeUnit.MILLISECONDS);
122+
123+
} catch (RejectedExecutionException e) {
124+
logger.warn("Unable to start collecting Gauges: " + e.getMessage());
125+
}
126+
}
127+
128+
public long updateGaugeCollection(
129+
ApplicationProcessState applicationProcessState, Timer gaugeCollectionTimer) {
130+
if (isCollectingGauges) {
131+
stopCollectingGauges();
132+
}
133+
return startCollectingGauges(applicationProcessState, gaugeCollectionTimer);
134+
}
135+
106136
/**
107137
* Starts the collection of available gauges for the given {@code sessionId} and {@code
108138
* applicationProcessState}. The collected Gauge Metrics will be flushed at regular intervals.
@@ -190,7 +220,7 @@ private long startCollectingGauges(ApplicationProcessState appState, Timer refer
190220
* this.stopCollectingGauges()} should always be called from the same thread.
191221
*/
192222
public void stopCollectingGauges() {
193-
if (this.sessionId == null) {
223+
if (!this.isCollectingGauges) {
194224
return;
195225
}
196226

@@ -219,6 +249,7 @@ public void stopCollectingGauges() {
219249
TimeUnit.MILLISECONDS);
220250

221251
this.sessionId = null;
252+
this.isCollectingGauges = false;
222253
this.applicationProcessState = ApplicationProcessState.APPLICATION_PROCESS_STATE_UNKNOWN;
223254
}
224255

@@ -253,16 +284,16 @@ private void syncFlush(String sessionId, ApplicationProcessState appState) {
253284
/**
254285
* Log the Gauge Metadata information to the transport.
255286
*
256-
* @param aqsSessionId The {@link PerfSession#aqsSessionId()} ()} to which the collected Gauge Metrics
287+
* @param sessionId The {@link PerfSession#sessionId()} ()} to which the collected Gauge Metrics
257288
* should be associated with.
258289
* @param appState The {@link ApplicationProcessState} for which these gauges are collected.
259290
* @return true if GaugeMetadata was logged, false otherwise.
260291
*/
261-
public boolean logGaugeMetadata(String aqsSessionId, ApplicationProcessState appState) {
292+
public boolean logGaugeMetadata(String sessionId, ApplicationProcessState appState) {
262293
if (gaugeMetadataManager != null) {
263294
GaugeMetric gaugeMetric =
264295
GaugeMetric.newBuilder()
265-
.setSessionId(aqsSessionId)
296+
.setSessionId(sessionId)
266297
.setGaugeMetadata(getGaugeMetadata())
267298
.build();
268299
transportManager.log(gaugeMetric, appState);
@@ -335,6 +366,22 @@ public void collectGaugeMetricOnce(Timer referenceTime) {
335366
collectGaugeMetricOnce(cpuGaugeCollector.get(), memoryGaugeCollector.get(), referenceTime);
336367
}
337368

369+
public void logExistingGaugeMetrics(
370+
String sessionId, ApplicationProcessState applicationProcessState) {
371+
// Flush any data that was collected and associate it with the given session ID and
372+
// applicationProcessState.
373+
@SuppressWarnings("FutureReturnValueIgnored")
374+
ScheduledFuture<?> unusedFuture =
375+
gaugeManagerExecutor
376+
.get()
377+
.schedule(
378+
() -> {
379+
syncFlush(sessionId, applicationProcessState);
380+
},
381+
TIME_TO_WAIT_BEFORE_FLUSHING_GAUGES_QUEUE_MS,
382+
TimeUnit.MILLISECONDS);
383+
}
384+
338385
private static void collectGaugeMetricOnce(
339386
CpuGaugeCollector cpuGaugeCollector,
340387
MemoryGaugeCollector memoryGaugeCollector,
@@ -405,4 +452,10 @@ private long getMemoryGaugeCollectionFrequencyMs(
405452
return memoryGaugeCollectionFrequency;
406453
}
407454
}
455+
456+
private long getGaugeLoggingFrequency(ApplicationProcessState applicationProcessState) {
457+
return Math.min(
458+
getMemoryGaugeCollectionFrequencyMs(applicationProcessState),
459+
getCpuGaugeCollectionFrequencyMs(applicationProcessState));
460+
}
408461
}

0 commit comments

Comments
 (0)