Skip to content

Commit 2dd5f1e

Browse files
committed
convert perf session to use aqs support session id
1 parent fcd270c commit 2dd5f1e

File tree

10 files changed

+120
-110
lines changed

10 files changed

+120
-110
lines changed

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

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.google.firebase.perf.config.RemoteConfigManager;
3535
import com.google.firebase.perf.logging.AndroidLogger;
3636
import com.google.firebase.perf.logging.ConsoleUrlGenerator;
37+
import com.google.firebase.perf.logging.DebugEnforcementCheck;
3738
import com.google.firebase.perf.metrics.HttpMetric;
3839
import com.google.firebase.perf.metrics.Trace;
3940
import com.google.firebase.perf.session.FirebasePerformanceSessionSubscriber;
@@ -43,6 +44,7 @@
4344
import com.google.firebase.perf.util.ImmutableBundle;
4445
import com.google.firebase.perf.util.Timer;
4546
import com.google.firebase.remoteconfig.RemoteConfigComponent;
47+
import com.google.firebase.sessions.BuildConfig;
4648
import com.google.firebase.sessions.api.FirebaseSessionsDependencies;
4749
import java.lang.annotation.Retention;
4850
import java.lang.annotation.RetentionPolicy;
@@ -169,6 +171,7 @@ public static FirebasePerformance getInstance() {
169171
this.mMetadataBundle = new ImmutableBundle(new Bundle());
170172
return;
171173
}
174+
DebugEnforcementCheck.setEnforcement(BuildConfig.DEBUG);
172175

173176
TransportManager.getInstance()
174177
.initialize(firebaseApp, firebaseInstallationsApi, transportFactoryProvider);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.google.firebase.perf.logging
2+
3+
class DebugEnforcementCheck {
4+
companion object {
5+
/** When enabled, failed preconditions will cause assertion errors for debugging. */
6+
@JvmStatic var enforcement: Boolean = false
7+
private var logger: AndroidLogger = AndroidLogger.getInstance()
8+
9+
public fun checkSession(isAqsAvailable: Boolean, failureMessage: String) {
10+
if (!isAqsAvailable) {
11+
Companion.logger.debug(failureMessage)
12+
assert(!enforcement) { failureMessage }
13+
}
14+
}
15+
}
16+
}

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

+2-14
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,16 @@ package com.google.firebase.perf.session
1919
import com.google.firebase.perf.session.gauges.GaugeManager
2020
import com.google.firebase.perf.v1.ApplicationProcessState
2121
import com.google.firebase.sessions.api.SessionSubscriber
22-
import java.util.UUID
2322

2423
class FirebasePerformanceSessionSubscriber(override val isDataCollectionEnabled: Boolean) :
2524
SessionSubscriber {
2625

2726
override val sessionSubscriberName: SessionSubscriber.Name = SessionSubscriber.Name.PERFORMANCE
2827

2928
override fun onSessionChanged(sessionDetails: SessionSubscriber.SessionDetails) {
30-
val currentPerfSession = SessionManager.getInstance().perfSession()
31-
32-
// A [PerfSession] was created before a session was started.
33-
if (currentPerfSession.aqsSessionId() == null) {
34-
currentPerfSession.setAQSId(sessionDetails)
35-
GaugeManager.getInstance()
36-
.logGaugeMetadata(currentPerfSession.aqsSessionId(), ApplicationProcessState.FOREGROUND)
37-
return
38-
}
39-
40-
val updatedSession = PerfSession.createWithId(UUID.randomUUID().toString())
41-
updatedSession.setAQSId(sessionDetails)
29+
val updatedSession = PerfSession.createWithId(sessionDetails.sessionId)
4230
SessionManager.getInstance().updatePerfSession(updatedSession)
4331
GaugeManager.getInstance()
44-
.logGaugeMetadata(updatedSession.aqsSessionId(), ApplicationProcessState.FOREGROUND)
32+
.logGaugeMetadata(updatedSession.sessionId(), ApplicationProcessState.FOREGROUND)
4533
}
4634
}

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

+31-41
Original file line numberDiff line numberDiff line change
@@ -23,62 +23,53 @@
2323
import com.google.firebase.perf.util.Clock;
2424
import com.google.firebase.perf.util.Timer;
2525
import com.google.firebase.perf.v1.SessionVerbosity;
26-
import com.google.firebase.sessions.api.SessionSubscriber;
2726
import java.util.List;
27+
import java.util.UUID;
2828
import java.util.concurrent.TimeUnit;
2929

3030
/** Details of a session including a unique Id and related information. */
3131
public class PerfSession implements Parcelable {
32-
33-
private final String sessionId;
3432
private final Timer creationTime;
35-
@Nullable private String aqsSessionId;
36-
33+
private final String sessionId;
3734
private boolean isGaugeAndEventCollectionEnabled = false;
35+
public final boolean isAqsReady;
3836

3937
/*
4038
* Creates a PerfSession object and decides what metrics to collect.
4139
*/
42-
public static PerfSession createWithId(@NonNull String sessionId) {
43-
String prunedSessionId = sessionId.replace("-", "");
44-
PerfSession session = new PerfSession(prunedSessionId, new Clock());
45-
session.setGaugeAndEventCollectionEnabled(shouldCollectGaugesAndEvents());
46-
40+
public static PerfSession createWithId(@Nullable String aqsSessionId) {
41+
String sessionId = UUID.randomUUID().toString().replace("-", "");
42+
Boolean isAqsReady = false;
43+
if (aqsSessionId != null) {
44+
sessionId = aqsSessionId;
45+
isAqsReady = true;
46+
}
47+
PerfSession session = new PerfSession(sessionId, new Clock(), isAqsReady);
48+
session.setGaugeAndEventCollectionEnabled(shouldCollectGaugesAndEvents(sessionId));
4749
return session;
4850
}
4951

5052
/** Creates a PerfSession with the provided {@code sessionId} and {@code clock}. */
5153
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
52-
public PerfSession(String sessionId, Clock clock) {
54+
public PerfSession(String sessionId, Clock clock, boolean isAqsReady) {
5355
this.sessionId = sessionId;
56+
this.isAqsReady = isAqsReady;
5457
creationTime = clock.getTime();
5558
}
5659

5760
private PerfSession(@NonNull Parcel in) {
5861
super();
5962
sessionId = in.readString();
6063
isGaugeAndEventCollectionEnabled = in.readByte() != 0;
64+
isAqsReady = in.readByte() != 0;
6165
creationTime = in.readParcelable(Timer.class.getClassLoader());
6266
}
6367

64-
/** Returns the sessionId of the session. */
68+
/** Returns the sessionId for the given session. */
6569
public String sessionId() {
6670
return sessionId;
6771
}
6872

69-
/** Returns the AQS sessionId for the given session. */
70-
@Nullable
71-
public String aqsSessionId() {
72-
return aqsSessionId;
73-
}
74-
75-
/** Sets the AQS sessionId for the given session. */
76-
public void setAQSId(SessionSubscriber.SessionDetails aqs) {
77-
if (aqsSessionId == null) {
78-
aqsSessionId = aqs.getSessionId();
79-
}
80-
}
81-
8273
/**
8374
* Returns a timer object that has been seeded with the system time at which the session began.
8475
*/
@@ -105,18 +96,6 @@ public boolean isVerbose() {
10596
return isGaugeAndEventCollectionEnabled;
10697
}
10798

108-
/** Checks if the current {@link com.google.firebase.perf.v1.PerfSession} is verbose or not. */
109-
@VisibleForTesting
110-
static boolean isVerbose(@NonNull com.google.firebase.perf.v1.PerfSession perfSession) {
111-
for (SessionVerbosity sessionVerbosity : perfSession.getSessionVerbosityList()) {
112-
if (sessionVerbosity == SessionVerbosity.GAUGES_AND_SYSTEM_EVENTS) {
113-
return true;
114-
}
115-
}
116-
117-
return false;
118-
}
119-
12099
/**
121100
* Checks if it has been more than {@link ConfigResolver#getSessionsMaxDurationMinutes()} time
122101
* since the creation time of the current session.
@@ -128,7 +107,6 @@ public boolean isSessionRunningTooLong() {
128107

129108
/** Creates and returns the proto object for PerfSession object. */
130109
public com.google.firebase.perf.v1.PerfSession build() {
131-
// TODO(b/394127311): Switch to using AQS.
132110
com.google.firebase.perf.v1.PerfSession.Builder sessionMetric =
133111
com.google.firebase.perf.v1.PerfSession.newBuilder().setSessionId(sessionId);
134112

@@ -179,11 +157,10 @@ public static com.google.firebase.perf.v1.PerfSession[] buildAndSort(
179157
}
180158

181159
/** If true, Session Gauge collection is enabled. */
182-
public static boolean shouldCollectGaugesAndEvents() {
160+
public static boolean shouldCollectGaugesAndEvents(String sessionId) {
183161
ConfigResolver configResolver = ConfigResolver.getInstance();
184-
185162
return configResolver.isPerformanceMonitoringEnabled()
186-
&& Math.random() < configResolver.getSessionsSamplingRate();
163+
&& (Math.abs(sessionId.hashCode() % 100) < configResolver.getSessionsSamplingRate() * 100);
187164
}
188165

189166
/**
@@ -207,6 +184,7 @@ public int describeContents() {
207184
public void writeToParcel(@NonNull Parcel out, int flags) {
208185
out.writeString(sessionId);
209186
out.writeByte((byte) (isGaugeAndEventCollectionEnabled ? 1 : 0));
187+
out.writeByte((byte) (isAqsReady ? 1 : 0));
210188
out.writeParcelable(creationTime, 0);
211189
}
212190

@@ -224,4 +202,16 @@ public PerfSession[] newArray(int size) {
224202
return new PerfSession[size];
225203
}
226204
};
205+
206+
/** Checks if the current {@link com.google.firebase.perf.v1.PerfSession} is verbose or not. */
207+
@VisibleForTesting
208+
static boolean isVerbose(@NonNull com.google.firebase.perf.v1.PerfSession perfSession) {
209+
for (SessionVerbosity sessionVerbosity : perfSession.getSessionVerbosityList()) {
210+
if (sessionVerbosity == SessionVerbosity.GAUGES_AND_SYSTEM_EVENTS) {
211+
return true;
212+
}
213+
}
214+
215+
return false;
216+
}
227217
}

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

+15-6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import androidx.annotation.Keep;
2020
import androidx.annotation.VisibleForTesting;
2121
import com.google.firebase.perf.application.AppStateMonitor;
22+
import com.google.firebase.perf.logging.AndroidLogger;
23+
import com.google.firebase.perf.logging.DebugEnforcementCheck;
2224
import com.google.firebase.perf.session.gauges.GaugeManager;
2325
import com.google.firebase.perf.v1.ApplicationProcessState;
2426
import com.google.firebase.perf.v1.GaugeMetadata;
@@ -28,11 +30,11 @@
2830
import java.util.Iterator;
2931
import java.util.Objects;
3032
import java.util.Set;
31-
import java.util.UUID;
3233

3334
/** Session manager to generate sessionIDs and broadcast to the application. */
3435
@Keep // Needed because of b/117526359.
3536
public class SessionManager {
37+
private final AndroidLogger logger = AndroidLogger.getInstance();
3638

3739
@SuppressLint("StaticFieldLeak")
3840
private static final SessionManager instance = new SessionManager();
@@ -50,15 +52,15 @@ public static SessionManager getInstance() {
5052

5153
/** Returns the currently active PerfSession. */
5254
public final PerfSession perfSession() {
55+
DebugEnforcementCheck.Companion.checkSession(
56+
perfSession.isAqsReady, "Access perf session from manger without aqs ready");
57+
5358
return perfSession;
5459
}
5560

5661
private SessionManager() {
57-
// Generate a new sessionID for every cold start.
58-
this(
59-
GaugeManager.getInstance(),
60-
PerfSession.createWithId(UUID.randomUUID().toString()),
61-
AppStateMonitor.getInstance());
62+
// session should quickly updated by session subscriber.
63+
this(GaugeManager.getInstance(), PerfSession.createWithId(null), AppStateMonitor.getInstance());
6264
}
6365

6466
@VisibleForTesting
@@ -83,6 +85,10 @@ public void setApplicationContext(final Context appContext) {
8385
* @see PerfSession#isSessionRunningTooLong()
8486
*/
8587
public void stopGaugeCollectionIfSessionRunningTooLong() {
88+
DebugEnforcementCheck.Companion.checkSession(
89+
perfSession.isAqsReady,
90+
"Session is not ready while trying to stopGaugeCollectionIfSessionRunningTooLong");
91+
8692
if (perfSession.isSessionRunningTooLong()) {
8793
gaugeManager.stopCollectingGauges();
8894
}
@@ -156,6 +162,9 @@ public void unregisterForSessionUpdates(WeakReference<SessionAwareObject> client
156162
}
157163

158164
private void startOrStopCollectingGauges(ApplicationProcessState appState) {
165+
DebugEnforcementCheck.Companion.checkSession(
166+
perfSession.isAqsReady, "Session is not ready while trying to startOrStopCollectingGauges");
167+
159168
if (perfSession.isGaugeAndEventCollectionEnabled()) {
160169
gaugeManager.startCollectingGauges(perfSession, appState);
161170
} else {

firebase-perf/src/test/java/com/google/firebase/perf/application/AppStateMonitorTest.java

+3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
import com.google.firebase.perf.config.DeviceCacheManager;
4040
import com.google.firebase.perf.metrics.NetworkRequestMetricBuilder;
4141
import com.google.firebase.perf.metrics.Trace;
42+
import com.google.firebase.perf.session.PerfSession;
43+
import com.google.firebase.perf.session.SessionManager;
4244
import com.google.firebase.perf.session.gauges.GaugeManager;
4345
import com.google.firebase.perf.transport.TransportManager;
4446
import com.google.firebase.perf.util.Clock;
@@ -80,6 +82,7 @@ public class AppStateMonitorTest extends FirebasePerformanceTestBase {
8082
@Before
8183
public void setUp() {
8284
currentTime = 0;
85+
SessionManager.getInstance().updatePerfSession(PerfSession.createWithId("sessionId"));
8386
initMocks(this);
8487
doAnswer((Answer<Timer>) invocationOnMock -> new Timer(currentTime)).when(clock).getTime();
8588

0 commit comments

Comments
 (0)