Skip to content

Commit 2d357bc

Browse files
committed
Upload some changes for gauge manager changes
1 parent e5bc537 commit 2d357bc

File tree

5 files changed

+148
-105
lines changed

5 files changed

+148
-105
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@
3737
import com.google.firebase.perf.metrics.HttpMetric;
3838
import com.google.firebase.perf.metrics.Trace;
3939
import com.google.firebase.perf.session.FirebasePerformanceSessionSubscriber;
40-
import com.google.firebase.sessions.api.SessionSubscriber;
4140
import com.google.firebase.perf.session.SessionManager;
4241
import com.google.firebase.perf.transport.TransportManager;
4342
import com.google.firebase.perf.util.Constants;
4443
import com.google.firebase.perf.util.ImmutableBundle;
4544
import com.google.firebase.perf.util.Timer;
4645
import com.google.firebase.remoteconfig.RemoteConfigComponent;
4746
import com.google.firebase.sessions.api.FirebaseSessionsDependencies;
47+
import com.google.firebase.sessions.api.SessionSubscriber;
4848
import java.lang.annotation.Retention;
4949
import java.lang.annotation.RetentionPolicy;
5050
import java.net.URL;
@@ -187,7 +187,8 @@ public static FirebasePerformance getInstance() {
187187
sessionManager.setApplicationContext(appContext);
188188

189189
mPerformanceCollectionForceEnabledState = configResolver.getIsPerformanceCollectionEnabled();
190-
this.sessionSubscriber = new FirebasePerformanceSessionSubscriber(isPerformanceCollectionEnabled());
190+
this.sessionSubscriber =
191+
new FirebasePerformanceSessionSubscriber(isPerformanceCollectionEnabled());
191192
FirebaseSessionsDependencies.register(this.sessionSubscriber);
192193

193194
if (logger.isLogcatEnabled() && isPerformanceCollectionEnabled()) {

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

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
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.session.gauges.GaugeManager;
2324
import com.google.firebase.perf.v1.ApplicationProcessState;
2425
import com.google.firebase.perf.v1.GaugeMetadata;
@@ -32,7 +33,7 @@
3233

3334
/** Session manager to generate sessionIDs and broadcast to the application. */
3435
@Keep // Needed because of b/117526359.
35-
public class SessionManager {
36+
public class SessionManager extends AppStateUpdateHandler {
3637

3738
@SuppressLint("StaticFieldLeak")
3839
private static final SessionManager instance = new SessionManager();
@@ -69,6 +70,18 @@ public SessionManager(
6970
this.appStateMonitor = appStateMonitor;
7071
}
7172

73+
@Override
74+
public void onUpdateAppState(ApplicationProcessState newAppState) {
75+
super.onUpdateAppState(newAppState);
76+
if (appStateMonitor.isColdStart()) {
77+
// We want the Session to remain unchanged if this is a cold start of the app since we already
78+
// update the PerfSession in FirebasePerfProvider#onAttachInfo().
79+
return;
80+
}
81+
82+
updateGaugeCollection(newAppState);
83+
}
84+
7285
/**
7386
* Finalizes gauge initialization during cold start. This must be called before app start finishes
7487
* (currently that is before onResume finishes) to ensure gauge collection starts on time.
@@ -118,7 +131,8 @@ public void updatePerfSession(PerfSession perfSession) {
118131
}
119132

120133
// Start of stop the gauge data collection.
121-
startOrStopCollectingGauges(appStateMonitor.getAppState());
134+
startOrStopCollectingGauges();
135+
updateGaugeCollection(appStateMonitor.getAppState());
122136
}
123137

124138
/**
@@ -128,7 +142,7 @@ public void updatePerfSession(PerfSession perfSession) {
128142
* this does not reset the perfSession.
129143
*/
130144
public void initializeGaugeCollection() {
131-
startOrStopCollectingGauges(ApplicationProcessState.FOREGROUND);
145+
startOrStopCollectingGauges();
132146
}
133147

134148
/**
@@ -155,14 +169,18 @@ public void unregisterForSessionUpdates(WeakReference<SessionAwareObject> client
155169
}
156170
}
157171

158-
private void startOrStopCollectingGauges(ApplicationProcessState appState) {
172+
private void startOrStopCollectingGauges() {
159173
if (perfSession.isGaugeAndEventCollectionEnabled()) {
160-
gaugeManager.startCollectingGauges(perfSession, appState);
174+
gaugeManager.startCollectingGauges(perfSession);
161175
} else {
162176
gaugeManager.stopCollectingGauges();
163177
}
164178
}
165179

180+
private void updateGaugeCollection(ApplicationProcessState applicationProcessState) {
181+
gaugeManager.updateGaugeCollection(applicationProcessState);
182+
}
183+
166184
@VisibleForTesting
167185
public void setPerfSession(PerfSession perfSession) {
168186
this.perfSession = perfSession;

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

Lines changed: 60 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,11 @@ public class GaugeManager {
6060

6161
@Nullable private GaugeMetadataManager gaugeMetadataManager;
6262
@Nullable private ScheduledFuture<?> gaugeManagerDataCollectionJob = null;
63-
@Nullable private String sessionId = null;
64-
@Nullable private String aqsSessionId = null;
65-
private ApplicationProcessState applicationProcessState =
66-
ApplicationProcessState.APPLICATION_PROCESS_STATE_UNKNOWN;
63+
@Nullable private PerfSession session = null;
64+
65+
// The default value for application process state is Foreground. This will be updated based on
66+
// app state changes.
67+
private ApplicationProcessState applicationProcessState = ApplicationProcessState.FOREGROUND;
6768

6869
// TODO(b/258263016): Migrate to go/firebase-android-executors
6970
@SuppressLint("ThreadPoolCreation")
@@ -104,48 +105,34 @@ public static synchronized GaugeManager getInstance() {
104105
return instance;
105106
}
106107

107-
/**
108-
* Starts the collection of available gauges for the given {@code sessionId} and {@code
109-
* applicationProcessState}. The collected Gauge Metrics will be flushed at regular intervals.
110-
*
111-
* <p>GaugeManager can only collect gauges for one session at a time, and if this method is called
112-
* again with the same or new sessionId while it's already collecting gauges, all future gauges
113-
* will then be associated with the same or new sessionId and applicationProcessState.
114-
*
115-
* @param session The {@link PerfSession} to which the collected gauges will be associated with.
116-
* @param applicationProcessState The {@link ApplicationProcessState} the collected GaugeMetrics
117-
* will be associated with.
118-
* @note: This method is NOT thread safe - {@link this.startCollectingGauges()} and {@link
119-
* this.stopCollectingGauges()} should always be called from the same thread.
120-
*/
121-
public void startCollectingGauges(
122-
PerfSession session, ApplicationProcessState applicationProcessState) {
123-
if (this.sessionId != null) {
124-
stopCollectingGauges();
108+
public void updateGaugeCollection(ApplicationProcessState applicationProcessState) {
109+
if (gaugeManagerDataCollectionJob != null) {
110+
gaugeManagerDataCollectionJob.cancel(false);
125111
}
126112

127-
long collectionFrequency = startCollectingGauges(applicationProcessState, session.getTimer());
128-
if (collectionFrequency == INVALID_GAUGE_COLLECTION_FREQUENCY) {
129-
logger.warn("Invalid gauge collection frequency. Unable to start collecting Gauges.");
113+
if (session == null || !session.isGaugeAndEventCollectionEnabled()) {
114+
logger.warn("Not starting gauge collection.");
115+
stopCollectingGauges();
130116
return;
131117
}
132118

133-
this.sessionId = session.sessionId();
134-
this.aqsSessionId = session.aqsSessionId();
135-
this.applicationProcessState = applicationProcessState;
119+
if (session.aqsSessionId() == null) {
120+
logger.warn("Not starting gauge collection.");
121+
}
136122

137-
// This is needed, otherwise the Runnable might use a stale value.
138-
final String sessionIdForScheduledTask = aqsSessionId;
139-
final ApplicationProcessState applicationProcessStateForScheduledTask = applicationProcessState;
123+
long collectionFrequency =
124+
Math.min(
125+
getCpuGaugeCollectionFrequencyMs(applicationProcessState),
126+
getMemoryGaugeCollectionFrequencyMs(applicationProcessState));
127+
String sessionIdForScheduledTask = session.aqsSessionId();
140128

141-
// TODO(b/394127311): Switch to using AQS.
142129
try {
143130
gaugeManagerDataCollectionJob =
144131
gaugeManagerExecutor
145132
.get()
146133
.scheduleWithFixedDelay(
147134
() -> {
148-
syncFlush(sessionIdForScheduledTask, applicationProcessStateForScheduledTask);
135+
syncFlush(sessionIdForScheduledTask, applicationProcessState);
149136
},
150137
/* initialDelay= */ collectionFrequency
151138
* APPROX_NUMBER_OF_DATA_POINTS_PER_GAUGE_METRIC,
@@ -155,6 +142,36 @@ public void startCollectingGauges(
155142
} catch (RejectedExecutionException e) {
156143
logger.warn("Unable to start collecting Gauges: " + e.getMessage());
157144
}
145+
146+
if (this.applicationProcessState != applicationProcessState) {
147+
this.applicationProcessState = applicationProcessState;
148+
149+
// If there's a change in App State - update the gauge collection frequency as well.
150+
stopCollectingGauges();
151+
startCollectingGauges(applicationProcessState, this.session.getTimer());
152+
}
153+
}
154+
155+
/**
156+
* Starts the collection of available gauges for the given {@code session}.
157+
*
158+
* <p>GaugeManager can only collect gauges for one session at a time, and if this method is called
159+
* again with the same or new sessionId while it's already collecting gauges, all future gauges
160+
* will then be associated with the same or new sessionId and applicationProcessState.
161+
*
162+
* @param session The {@link PerfSession} to which the collected gauges will be associated with.
163+
* @note: This method is NOT thread safe - {@link this.startCollectingGauges()} and {@link
164+
* this.stopCollectingGauges()} should always be called from the same thread.
165+
*/
166+
public void startCollectingGauges(PerfSession session) {
167+
if (this.session != null) {
168+
stopCollectingGauges();
169+
}
170+
171+
long collectionFrequency = startCollectingGauges(applicationProcessState, session.getTimer());
172+
if (collectionFrequency == INVALID_GAUGE_COLLECTION_FREQUENCY) {
173+
logger.warn("Invalid gauge collection frequency. Unable to start collecting Gauges.");
174+
}
158175
}
159176

160177
/**
@@ -192,12 +209,14 @@ private long startCollectingGauges(ApplicationProcessState appState, Timer refer
192209
* this.stopCollectingGauges()} should always be called from the same thread.
193210
*/
194211
public void stopCollectingGauges() {
195-
if (this.sessionId == null) {
212+
if (this.session == null) {
196213
return;
197214
}
198215

199216
// This is needed, otherwise the Runnable might use a stale value.
200-
final String sessionIdForScheduledTask = aqsSessionId;
217+
218+
// AQS is guaranteed to be available when stopping gauge collection.
219+
final String sessionIdForScheduledTask = session.aqsSessionId();
201220
final ApplicationProcessState applicationProcessStateForScheduledTask = applicationProcessState;
202221

203222
cpuGaugeCollector.get().stopCollecting();
@@ -207,7 +226,6 @@ public void stopCollectingGauges() {
207226
gaugeManagerDataCollectionJob.cancel(false);
208227
}
209228

210-
// TODO(b/394127311): Switch to using AQS.
211229
// Flush any data that was collected for this session one last time.
212230
@SuppressWarnings("FutureReturnValueIgnored")
213231
ScheduledFuture<?> unusedFuture =
@@ -220,8 +238,7 @@ public void stopCollectingGauges() {
220238
TIME_TO_WAIT_BEFORE_FLUSHING_GAUGES_QUEUE_MS,
221239
TimeUnit.MILLISECONDS);
222240

223-
this.sessionId = null;
224-
this.applicationProcessState = ApplicationProcessState.APPLICATION_PROCESS_STATE_UNKNOWN;
241+
this.session = null;
225242
}
226243

227244
/**
@@ -407,4 +424,9 @@ private long getMemoryGaugeCollectionFrequencyMs(
407424
return memoryGaugeCollectionFrequency;
408425
}
409426
}
427+
428+
@VisibleForTesting
429+
void setApplicationProcessState(ApplicationProcessState applicationProcessState) {
430+
this.applicationProcessState = applicationProcessState;
431+
}
410432
}

firebase-perf/src/test/java/com/google/firebase/perf/session/SessionManagerTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ public void testUpdatePerfSessionStartsCollectingGaugesIfSessionIsVerbose() {
144144
testSessionManager.setApplicationContext(mockApplicationContext);
145145

146146
verify(mockGaugeManager, times(1)).initializeGaugeMetadataManager(mockApplicationContext);
147-
verify(mockGaugeManager, times(1))
148-
.startCollectingGauges(newSession, ApplicationProcessState.FOREGROUND);
147+
verify(mockGaugeManager, times(1)).startCollectingGauges(newSession);
148+
verify(mockGaugeManager, times(1)).updateGaugeCollection(ApplicationProcessState.FOREGROUND);
149149
}
150150

151151
@Test

0 commit comments

Comments
 (0)