Skip to content

Update GaugeManager and SessionManager to separate app state changes and PerfSession changes #6876

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: fireperf-aqs
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,8 @@ public FirebasePerfEarly(
uiExecutor.execute(new AppStartTrace.StartFromBackgroundRunnable(appStartTrace));
}

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

// In the case of cold start, we create a session and start collecting gauges as early as
// possible.
// There is code in SessionManager that prevents us from resetting the session twice in case
// of app cold start.
SessionManager.getInstance().initializeGaugeCollection();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,19 @@ class FirebasePerformanceSessionSubscriber(override val isDataCollectionEnabled:

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

if (currentPerfSession.isLegacy() && currentPerfSession.isVerbose) {
GaugeManager.getInstance()
.logGaugeMetadata(sessionDetails.sessionId, ApplicationProcessState.FOREGROUND)
GaugeManager.getInstance()
.logExistingGaugeMetrics(sessionDetails.sessionId, ApplicationProcessState.FOREGROUND)
}

val updatedSession = PerfSession.createWithId(sessionDetails.sessionId)
SessionManager.getInstance().updatePerfSession(updatedSession)
GaugeManager.getInstance()
.logGaugeMetadata(updatedSession.sessionId(), ApplicationProcessState.FOREGROUND)
SessionManager.getInstance().updateGaugeCollectionOnNewSession()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
public class PerfSession implements Parcelable {
private final Timer creationTime;
private final String sessionId;
private boolean isGaugeAndEventCollectionEnabled = false;
private boolean isGaugeAndEventCollectionEnabled = true;

/*
* Creates a PerfSession object and decides what metrics to collect.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ public class GaugeManager {
private final TransportManager transportManager;

@Nullable private GaugeMetadataManager gaugeMetadataManager;
@Nullable private ScheduledFuture gaugeManagerDataCollectionJob = null;
@Nullable private ScheduledFuture<?> gaugeManagerDataCollectionJob = null;
@Nullable private String sessionId = null;

private boolean isCollectingGauges = false;
private ApplicationProcessState applicationProcessState =
ApplicationProcessState.APPLICATION_PROCESS_STATE_UNKNOWN;

Expand Down Expand Up @@ -103,6 +105,34 @@ public static synchronized GaugeManager getInstance() {
return instance;
}

public void updateGaugeLogging(
String sessionId, ApplicationProcessState applicationProcessState, long collectionFrequency) {
try {
gaugeManagerDataCollectionJob =
gaugeManagerExecutor
.get()
.scheduleWithFixedDelay(
() -> {
syncFlush(sessionId, applicationProcessState);
},
/* initialDelay= */ collectionFrequency
* APPROX_NUMBER_OF_DATA_POINTS_PER_GAUGE_METRIC,
/* period= */ collectionFrequency * APPROX_NUMBER_OF_DATA_POINTS_PER_GAUGE_METRIC,
TimeUnit.MILLISECONDS);

} catch (RejectedExecutionException e) {
logger.warn("Unable to start collecting Gauges: " + e.getMessage());
}
}

public long updateGaugeCollection(
ApplicationProcessState applicationProcessState, Timer gaugeCollectionTimer) {
if (isCollectingGauges) {
stopCollectingGauges();
}
return startCollectingGauges(applicationProcessState, gaugeCollectionTimer);
}

/**
* Starts the collection of available gauges for the given {@code sessionId} and {@code
* applicationProcessState}. The collected Gauge Metrics will be flushed at regular intervals.
Expand Down Expand Up @@ -190,7 +220,7 @@ private long startCollectingGauges(ApplicationProcessState appState, Timer refer
* this.stopCollectingGauges()} should always be called from the same thread.
*/
public void stopCollectingGauges() {
if (this.sessionId == null) {
if (!this.isCollectingGauges) {
return;
}

Expand Down Expand Up @@ -219,6 +249,7 @@ public void stopCollectingGauges() {
TimeUnit.MILLISECONDS);

this.sessionId = null;
this.isCollectingGauges = false;
this.applicationProcessState = ApplicationProcessState.APPLICATION_PROCESS_STATE_UNKNOWN;
}

Expand Down Expand Up @@ -253,16 +284,16 @@ private void syncFlush(String sessionId, ApplicationProcessState appState) {
/**
* Log the Gauge Metadata information to the transport.
*
* @param aqsSessionId The {@link PerfSession#aqsSessionId()} ()} to which the collected Gauge Metrics
* @param sessionId The {@link PerfSession#sessionId()} ()} to which the collected Gauge Metrics
* should be associated with.
* @param appState The {@link ApplicationProcessState} for which these gauges are collected.
* @return true if GaugeMetadata was logged, false otherwise.
*/
public boolean logGaugeMetadata(String aqsSessionId, ApplicationProcessState appState) {
public boolean logGaugeMetadata(String sessionId, ApplicationProcessState appState) {
if (gaugeMetadataManager != null) {
GaugeMetric gaugeMetric =
GaugeMetric.newBuilder()
.setSessionId(aqsSessionId)
.setSessionId(sessionId)
.setGaugeMetadata(getGaugeMetadata())
.build();
transportManager.log(gaugeMetric, appState);
Expand Down Expand Up @@ -335,6 +366,22 @@ public void collectGaugeMetricOnce(Timer referenceTime) {
collectGaugeMetricOnce(cpuGaugeCollector.get(), memoryGaugeCollector.get(), referenceTime);
}

public void logExistingGaugeMetrics(
String sessionId, ApplicationProcessState applicationProcessState) {
// Flush any data that was collected and associate it with the given session ID and
// applicationProcessState.
@SuppressWarnings("FutureReturnValueIgnored")
ScheduledFuture<?> unusedFuture =
gaugeManagerExecutor
.get()
.schedule(
() -> {
syncFlush(sessionId, applicationProcessState);
},
TIME_TO_WAIT_BEFORE_FLUSHING_GAUGES_QUEUE_MS,
TimeUnit.MILLISECONDS);
}

private static void collectGaugeMetricOnce(
CpuGaugeCollector cpuGaugeCollector,
MemoryGaugeCollector memoryGaugeCollector,
Expand Down Expand Up @@ -405,4 +452,10 @@ private long getMemoryGaugeCollectionFrequencyMs(
return memoryGaugeCollectionFrequency;
}
}

private long getGaugeLoggingFrequency(ApplicationProcessState applicationProcessState) {
return Math.min(
getMemoryGaugeCollectionFrequencyMs(applicationProcessState),
getCpuGaugeCollectionFrequencyMs(applicationProcessState));
}
}
Loading