Skip to content
Merged
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 @@ -9,8 +9,9 @@ public class CCAnalyticsParam {
public static final String USER_CID = "user_cid";
static final String BUILD_NUMBER = "build_number";
static final String CC_APP_ID = "cc_app_id";
static final String CC_APP_NAME = "cc_app_name";
static final String CC_APP_BUILD_PROFILE_ID = "cc_app_build_profile_id";
static final String CCHQ_DOMAIN = "cchq_domain";
public static final String CCHQ_DOMAIN = "cchq_domain";
static final String SERVER = "server";
static final String FREE_DISK = "free_disk";
static final String CCC_ENABLED = "ccc_enabled";
Expand All @@ -23,7 +24,7 @@ public class CCAnalyticsParam {
static final String REASON = "reason";
static final String RESULT = "result";
static final String UI_STATE = "uite_state";
static final String USERNAME = "username";
public static final String USERNAME = "username";
static final String FORM_ID = "form_id";
static final String REQUEST_ID = "request_id";
static final String RESULT_CODE = "result_code";
Expand Down
38 changes: 38 additions & 0 deletions app/src/org/commcare/google/services/analytics/CCPerfMonitoring.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.commcare.google.services.analytics

import com.google.firebase.perf.FirebasePerformance
import com.google.firebase.perf.metrics.Trace
import org.commcare.android.logging.ReportingUtils
import org.javarosa.core.services.Logger

object CCPerfMonitoring {
// Traces
// Measures the duration of synchronous case list loading
const val TRACE_SYNC_ENTITY_LIST_LOADING = "sync_case_list_loading"

// Attributes
const val ATTR_NUM_CASES_LOADED = "number_of_cases_loaded"

fun startTracing (traceName: String): Trace? {
try {
val trace = FirebasePerformance.getInstance().newTrace(traceName)
trace.putAttribute(CCAnalyticsParam.CCHQ_DOMAIN, ReportingUtils.getDomain())
trace.putAttribute(CCAnalyticsParam.CC_APP_ID, ReportingUtils.getAppId())
trace.putAttribute(CCAnalyticsParam.CC_APP_NAME, ReportingUtils.getAppName())
trace.putAttribute(CCAnalyticsParam.USERNAME, ReportingUtils.getUser())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually i think we should be using the same list of attributes as we send to analytics user properties here, think app id is definitely a big one that we should be including here.

trace.start();
return trace
} catch (exception: Exception) {
Logger.exception("Error starting perf trace: $traceName", exception)
}
return null
}

fun stopTracing(trace: Trace?) {
try {
trace?.stop();
} catch (exception: Exception) {
Logger.exception("Error starting perf trace: ${trace?.name}", exception)
}
}
}
8 changes: 6 additions & 2 deletions app/src/org/commcare/tasks/EntityLoaderHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class EntityLoaderHelper(
nodeset: TreeReference,
progressListener: EntityLoadingProgressListener
): Pair<List<Entity<TreeReference>>, List<TreeReference>>? {
if (factory !is AsyncNodeEntityFactory) {
if (!isAsyncNodeEntityFactory()) {
// if we are into synchronous mode, cancel background cache work for now to not lock the user db
CommCareApplication.instance().currentApp.primeEntityCacheHelper.cancelWork()
}
Expand All @@ -72,14 +72,18 @@ class EntityLoaderHelper(
return Pair<List<Entity<TreeReference>>, List<TreeReference>>(entities, references)
}
} finally {
if (factory !is AsyncNodeEntityFactory) {
if (!isAsyncNodeEntityFactory()) {
// Restart the cancelled task
PrimeEntityCacheHelper.schedulePrimeEntityCacheWorker()
}
}
return null
}

fun isAsyncNodeEntityFactory(): Boolean {
return factory is AsyncNodeEntityFactory
}

/**
* Primes the entity cache
*/
Expand Down
18 changes: 17 additions & 1 deletion app/src/org/commcare/tasks/EntityLoaderTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

import android.util.Pair;

import com.google.firebase.perf.metrics.Trace;

import org.commcare.android.logging.ForceCloseLogger;
import org.commcare.cases.entity.Entity;
import org.commcare.cases.entity.EntityLoadingProgressListener;
import org.commcare.google.services.analytics.CCPerfMonitoring;
import org.commcare.logging.XPathErrorLogger;
import org.commcare.suite.model.Detail;
import org.commcare.suite.model.EntityDatum;
Expand Down Expand Up @@ -50,7 +53,20 @@ public EntityLoaderTask(Detail detail, @Nullable EntityDatum entityDatum, Evalua
@Override
protected Pair<List<Entity<TreeReference>>, List<TreeReference>> doInBackground(TreeReference... nodeset) {
try {
return entityLoaderHelper.loadEntities(nodeset[0], this);
// Capture sync_case_list_loading trace for performance monitoring
Trace trace = null;
if (!entityLoaderHelper.isAsyncNodeEntityFactory()) {
trace = CCPerfMonitoring.INSTANCE.startTracing(CCPerfMonitoring.TRACE_SYNC_ENTITY_LIST_LOADING);
}
Pair<List<Entity<TreeReference>>, List<TreeReference>> entities = entityLoaderHelper.loadEntities(
nodeset[0], this);

if (trace != null && !entityLoaderHelper.isAsyncNodeEntityFactory()) {
trace.putAttribute(CCPerfMonitoring.ATTR_NUM_CASES_LOADED,
String.valueOf((entities == null || entities.first == null ? 0 : entities.first.size())));
CCPerfMonitoring.INSTANCE.stopTracing(trace);
Comment on lines +65 to +67
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

think all trace handling should be as fail safe as possible, as such think we should pass the attributes as a dictionary to the stopTracing method as well and have it call the trace.putAttribute on that dictionary in the catch all block itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I made this change on a different branch (for another trace), I will push PR this separately

}
return entities;
} catch (XPathException xe) {
XPathErrorLogger.INSTANCE.logErrorToCurrentApp(xe);
Logger.exception("Error during EntityLoaderTask: " + ForceCloseLogger.getStackTrace(xe), xe);
Expand Down
Loading