Skip to content

Update GaugeManager for AQS #6938

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

Merged
merged 17 commits into from
May 7, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ public NetworkRequestMetricBuilder setCustomAttributes(Map<String, String> attri
* point depending upon the current {@link PerfSession} verbosity.
*
* @see GaugeManager#collectGaugeMetricOnce(Timer)
* @see PerfSession#isGaugeAndEventCollectionEnabled()
* @see PerfSession#isVerbose()
*/
public NetworkRequestMetricBuilder setRequestStartTimeMicros(long time) {
SessionManager sessionManager = SessionManager.getInstance();
Expand All @@ -234,7 +234,7 @@ public NetworkRequestMetricBuilder setRequestStartTimeMicros(long time) {
builder.setClientStartTimeUs(time);
updateSession(perfSession);

if (perfSession.isGaugeAndEventCollectionEnabled()) {
if (perfSession.isVerbose()) {
gaugeManager.collectGaugeMetricOnce(perfSession.getTimer());
}

Expand Down Expand Up @@ -265,12 +265,12 @@ public long getTimeToResponseInitiatedMicros() {
* point depending upon the current {@link PerfSession} Verbosity.
*
* @see GaugeManager#collectGaugeMetricOnce(Timer)
* @see PerfSession#isGaugeAndEventCollectionEnabled()
* @see PerfSession#isVerbose()
*/
public NetworkRequestMetricBuilder setTimeToResponseCompletedMicros(long time) {
builder.setTimeToResponseCompletedUs(time);

if (SessionManager.getInstance().perfSession().isGaugeAndEventCollectionEnabled()) {
if (SessionManager.getInstance().perfSession().isVerbose()) {
gaugeManager.collectGaugeMetricOnce(SessionManager.getInstance().perfSession().getTimer());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ public void start() {

updateSession(perfSession);

if (perfSession.isGaugeAndEventCollectionEnabled()) {
if (perfSession.isVerbose()) {
gaugeManager.collectGaugeMetricOnce(perfSession.getTimer());
}
}
Expand All @@ -259,7 +259,7 @@ public void stop() {
if (!name.isEmpty()) {
transportManager.log(new TraceMetricBuilder(this).build(), getAppState());

if (SessionManager.getInstance().perfSession().isGaugeAndEventCollectionEnabled()) {
if (SessionManager.getInstance().perfSession().isVerbose()) {
gaugeManager.collectGaugeMetricOnce(
SessionManager.getInstance().perfSession().getTimer());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,15 @@ public static PerfSession createWithId(@Nullable String aqsSessionId) {
if (sessionId == null) {
sessionId = FirebaseSessionsHelperKt.createLegacySessionId();
}
PerfSession session = new PerfSession(sessionId, new Clock());
session.setGaugeAndEventCollectionEnabled(session.shouldCollectGaugesAndEvents());
return session;
return new PerfSession(sessionId, new Clock());
}

/** Creates a PerfSession with the provided {@code sessionId} and {@code clock}. */
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
public PerfSession(String sessionId, Clock clock) {
this.sessionId = sessionId;
creationTime = clock.getTime();
isGaugeAndEventCollectionEnabled = shouldCollectGaugesAndEvents();
}

private PerfSession(@NonNull Parcel in) {
Expand All @@ -72,20 +71,6 @@ public Timer getTimer() {
return creationTime;
}

/*
* Enables/Disables the gauge and event collection for the system.
*/
public void setGaugeAndEventCollectionEnabled(boolean enabled) {
isGaugeAndEventCollectionEnabled = enabled;
}

/*
* Returns if gauge and event collection is enabled for the system.
*/
public boolean isGaugeAndEventCollectionEnabled() {
return isGaugeAndEventCollectionEnabled;
}

/** Returns if the current session is verbose or not. */
public boolean isVerbose() {
return isGaugeAndEventCollectionEnabled;
Expand Down Expand Up @@ -152,13 +137,22 @@ public static com.google.firebase.perf.v1.PerfSession[] buildAndSort(
}

/** If true, Session Gauge collection is enabled. */
@VisibleForTesting
public boolean shouldCollectGaugesAndEvents() {
ConfigResolver configResolver = ConfigResolver.getInstance();
return configResolver.isPerformanceMonitoringEnabled()
&& (Math.abs(this.sessionId.hashCode() % 100)
< configResolver.getSessionsSamplingRate() * 100);
}

/*
* Enables/Disables whether the session is verbose or not.
*/
@VisibleForTesting
public void setGaugeAndEventCollectionEnabled(boolean enabled) {
isGaugeAndEventCollectionEnabled = enabled;
}

/**
* Describes the kinds of special objects contained in this Parcelable's marshalled
* representation. Please refer to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@
import android.content.Context;
import androidx.annotation.Keep;
import androidx.annotation.VisibleForTesting;
import com.google.firebase.perf.application.AppStateMonitor;
import com.google.firebase.perf.logging.FirebaseSessionsEnforcementCheck;
import com.google.firebase.perf.session.gauges.GaugeManager;
import com.google.firebase.perf.v1.ApplicationProcessState;
import com.google.firebase.perf.v1.GaugeMetadata;
import com.google.firebase.perf.v1.GaugeMetric;
import java.lang.ref.WeakReference;
Expand All @@ -37,7 +35,6 @@ public class SessionManager {
private static final SessionManager instance = new SessionManager();

private final GaugeManager gaugeManager;
private final AppStateMonitor appStateMonitor;
private final Set<WeakReference<SessionAwareObject>> clients = new HashSet<>();

private PerfSession perfSession;
Expand All @@ -49,23 +46,20 @@ public static SessionManager getInstance() {

/** Returns the currently active PerfSession. */
public final PerfSession perfSession() {
FirebaseSessionsEnforcementCheck.checkSession(
perfSession, "Access perf session from manger without aqs ready");
FirebaseSessionsEnforcementCheck.checkSession(perfSession, "PerfSession.perfSession()");

return perfSession;
}

private SessionManager() {
// session should quickly updated by session subscriber.
this(GaugeManager.getInstance(), PerfSession.createWithId(null), AppStateMonitor.getInstance());
this(GaugeManager.getInstance(), PerfSession.createWithId(null));
}

@VisibleForTesting
public SessionManager(
GaugeManager gaugeManager, PerfSession perfSession, AppStateMonitor appStateMonitor) {
public SessionManager(GaugeManager gaugeManager, PerfSession perfSession) {
this.gaugeManager = gaugeManager;
this.perfSession = perfSession;
this.appStateMonitor = appStateMonitor;
}

/**
Expand All @@ -83,8 +77,7 @@ public void setApplicationContext(final Context appContext) {
*/
public void stopGaugeCollectionIfSessionRunningTooLong() {
FirebaseSessionsEnforcementCheck.checkSession(
perfSession,
"Session is not ready while trying to stopGaugeCollectionIfSessionRunningTooLong");
perfSession, "SessionManager.stopGaugeCollectionIfSessionRunningTooLong");

if (perfSession.isSessionRunningTooLong()) {
gaugeManager.stopCollectingGauges();
Expand Down Expand Up @@ -123,7 +116,7 @@ public void updatePerfSession(PerfSession perfSession) {
}

// Start of stop the gauge data collection.
startOrStopCollectingGauges(appStateMonitor.getAppState());
startOrStopCollectingGauges();
}

/**
Expand All @@ -133,7 +126,7 @@ public void updatePerfSession(PerfSession perfSession) {
* this does not reset the perfSession.
*/
public void initializeGaugeCollection() {
startOrStopCollectingGauges(ApplicationProcessState.FOREGROUND);
startOrStopCollectingGauges();
}

/**
Expand All @@ -160,12 +153,11 @@ public void unregisterForSessionUpdates(WeakReference<SessionAwareObject> client
}
}

private void startOrStopCollectingGauges(ApplicationProcessState appState) {
FirebaseSessionsEnforcementCheck.checkSession(
perfSession, "Session is not ready while trying to startOrStopCollectingGauges");
private void startOrStopCollectingGauges() {
FirebaseSessionsEnforcementCheck.checkSession(perfSession, "startOrStopCollectingGauges");

if (perfSession.isGaugeAndEventCollectionEnabled()) {
gaugeManager.startCollectingGauges(perfSession, appState);
if (perfSession.isVerbose()) {
gaugeManager.startCollectingGauges(perfSession);
} else {
gaugeManager.stopCollectingGauges();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public class CpuGaugeCollector {
private final String procFileName;
private final long clockTicksPerSecond;

@Nullable private ScheduledFuture cpuMetricCollectorJob = null;
@Nullable private ScheduledFuture<?> cpuMetricCollectorJob = null;
private long cpuMetricCollectionRateMs = UNSET_CPU_METRIC_COLLECTION_RATE;

// TODO(b/258263016): Migrate to go/firebase-android-executors
Expand Down Expand Up @@ -166,6 +166,7 @@ private synchronized void scheduleCpuMetricCollectionWithRate(
CpuMetricReading currCpuReading = syncCollectCpuMetric(referenceTime);
if (currCpuReading != null) {
cpuMetricReadings.add(currCpuReading);
GaugeCounter.INSTANCE.incrementCounter();
}
},
/* initialDelay */ 0,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.firebase.perf.session.gauges

import java.util.concurrent.atomic.AtomicInteger

/**
* [GaugeCounter] is a thread-safe counter for gauge metrics. If the metrics count exceeds
* [MAX_METRIC_COUNT], it attempts to log the metrics to Firelog.
*/
object GaugeCounter {
private const val MAX_METRIC_COUNT = 25
private val counter = AtomicInteger(0)
private val gaugeManager: GaugeManager = GaugeManager.getInstance()

fun incrementCounter() {
val metricsCount = counter.incrementAndGet()

if (metricsCount >= MAX_METRIC_COUNT) {
gaugeManager.logGaugeMetrics()
}
}

fun decrementCounter() {
counter.decrementAndGet()
}
}
Loading
Loading