-
-
Notifications
You must be signed in to change notification settings - Fork 45
[Hotfix] Add perf monitoring trace for file encryption time #3496
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
[Hotfix] Add perf monitoring trace for file encryption time #3496
Conversation
📝 WalkthroughWalkthroughThis PR adds performance monitoring instrumentation for file encryption and storage operations. It introduces new trace name and attribute constants ( Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@app/src/org/commcare/models/encryption/EncryptionIO.java`:
- Around line 19-21: EncryptionIO currently imports java.nio.file.Files and
java.nio.file.Paths and uses Files.size(Paths.get(sourceFilePath)); replace
these with java.io.File usage to avoid API 26-only classes: remove the
java.nio.file.Files and java.nio.file.Paths imports, import java.io.File
instead, and change the size check to use new File(sourceFilePath).length()
wherever Files.size(Paths.get(...)) is used (e.g., the call in EncryptionIO that
references sourceFilePath); keep behavior identical otherwise and handle the
long return type from File.length().
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
app/src/org/commcare/google/services/analytics/CCPerfMonitoring.ktapp/src/org/commcare/models/database/HybridFileBackedSqlStorage.javaapp/src/org/commcare/models/encryption/EncryptionIO.javaapp/src/org/commcare/tasks/SaveToDiskTask.javaapp/src/org/commcare/utils/FileUtil.java
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-10T16:39:05.007Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3448
File: app/src/org/commcare/gis/EntityMapUtils.kt:214-234
Timestamp: 2025-12-10T16:39:05.007Z
Learning: In Kotlin files (here: app/src/org/commcare/gis/EntityMapUtils.kt), follow fail-fast guidance: treat conditions that indicate a programmer error or broken invariant as exceptions rather than defensive handling. If a condition represents a bug (e.g., internal API assumptions like array/list size mismatches), crash early to alert developers instead of attempting to recover. Use clear runtime exceptions (e.g., IllegalStateException, IllegalArgumentException) or assertions where appropriate, and avoid swallowing or masking bugs. Ensure invariants are checked and failures are surfaced with actionable messages for quick debugging.
Applied to files:
app/src/org/commcare/google/services/analytics/CCPerfMonitoring.kt
📚 Learning: 2025-05-22T14:28:35.959Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3121
File: app/src/org/commcare/activities/CommCareSetupActivity.java:360-364
Timestamp: 2025-05-22T14:28:35.959Z
Learning: In CommCareSetupActivity.java, the call to installFragment.showConnectErrorMessage() after fragment transactions is intentionally unguarded with null checks. This follows the app's design pattern where critical error paths prefer immediate crashes over silent failures, making potential issues immediately visible during development rather than hiding them with defensive programming.
Applied to files:
app/src/org/commcare/tasks/SaveToDiskTask.java
🧬 Code graph analysis (3)
app/src/org/commcare/models/encryption/EncryptionIO.java (1)
app/src/org/commcare/google/services/analytics/CCPerfMonitoring.kt (2)
startTracing(29-42)stopTracing(44-51)
app/src/org/commcare/tasks/SaveToDiskTask.java (2)
app/src/org/commcare/utils/FileUtil.java (1)
FileUtil(65-968)app/src/org/commcare/google/services/analytics/CCPerfMonitoring.kt (2)
startTracing(29-42)stopTracing(44-51)
app/src/org/commcare/models/database/HybridFileBackedSqlStorage.java (3)
app/src/org/commcare/CommCareApplication.java (1)
CommCareApplication(158-1255)app/src/org/commcare/google/services/analytics/CCPerfMonitoring.kt (2)
startTracing(29-42)stopTracing(44-51)app/src/org/commcare/utils/HashUtils.kt (1)
toString(13-13)
🔇 Additional comments (4)
app/src/org/commcare/utils/FileUtil.java (1)
70-70: LGTM — shared XML extension constant is clean and useful.
Line 70 looks good and improves consistency across callers.app/src/org/commcare/google/services/analytics/CCPerfMonitoring.kt (1)
15-27: LGTM — new trace and attribute constants are clear and consistent.
Lines 15 and 26–27 are straightforward additions.app/src/org/commcare/models/database/HybridFileBackedSqlStorage.java (1)
338-359: Nice, safe tracing integration in the file-write path.
Line 338–359 cleanly captures size/type attributes and stops tracing in a finally path.app/src/org/commcare/tasks/SaveToDiskTask.java (1)
266-281: LGTM — tracing around XML write is consistent and low-risk.
Line 266–281 correctly tags size and type and stops the trace in the finally path.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| import java.nio.file.Files; | ||
| import java.nio.file.Paths; | ||
| import java.security.InvalidKeyException; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
find . -name "EncryptionIO.java" -type fRepository: dimagi/commcare-android
Length of output: 125
🏁 Script executed:
find . -name "build.gradle" -o -name "AndroidManifest.xml" | head -20Repository: dimagi/commcare-android
Length of output: 270
🏁 Script executed:
head -n 60 ./app/src/org/commcare/models/encryption/EncryptionIO.java | cat -nRepository: dimagi/commcare-android
Length of output: 2726
🏁 Script executed:
grep -A 10 -B 2 "minSdk" ./app/build.gradleRepository: dimagi/commcare-android
Length of output: 484
🏁 Script executed:
grep -n "import java.io.File" ./app/src/org/commcare/models/encryption/EncryptionIO.javaRepository: dimagi/commcare-android
Length of output: 202
Replace java.nio.file APIs with java.io.File to ensure compatibility with minSdk 23.
Lines 19–20 import java.nio.file.Files and java.nio.file.Paths, which are only available from API 26. Line 51 uses Files.size(Paths.get(sourceFilePath)). Since the app's minSdkVersion is 23, this will crash at runtime on Android 6.x devices (API 23–25) with NoClassDefFoundError. Replace with new File(sourceFilePath).length().
🛠️ Suggested fix
-import java.nio.file.Files;
-import java.nio.file.Paths;
import java.security.InvalidKeyException;- attrs.put(CCPerfMonitoring.ATTR_FILE_SIZE_BYTES, Long.toString(Files.size(Paths.get(sourceFilePath))));
+ attrs.put(CCPerfMonitoring.ATTR_FILE_SIZE_BYTES, Long.toString(new File(sourceFilePath).length()));🤖 Prompt for AI Agents
In `@app/src/org/commcare/models/encryption/EncryptionIO.java` around lines 19 -
21, EncryptionIO currently imports java.nio.file.Files and java.nio.file.Paths
and uses Files.size(Paths.get(sourceFilePath)); replace these with java.io.File
usage to avoid API 26-only classes: remove the java.nio.file.Files and
java.nio.file.Paths imports, import java.io.File instead, and change the size
check to use new File(sourceFilePath).length() wherever
Files.size(Paths.get(...)) is used (e.g., the call in EncryptionIO that
references sourceFilePath); keep behavior identical otherwise and handle the
long return type from File.length().
|
@avazirna One other question -> Given the main goal of this is to compare performance pre-post the change to use Android keystore for encryption, it might be better to put the file size in buckets for ease of analysis. Not sure if that's easy to do on Firebase Performance UI or bigquery. |
| try { | ||
| Map<String, String> attrs = new HashMap<>(); | ||
| attrs.put(CCPerfMonitoring.ATTR_FILE_SIZE_BYTES, Long.toString(payload.getLength())); | ||
| attrs.put(CCPerfMonitoring.ATTR_FILE_TYPE, XML_EXTENSION); | ||
| CCPerfMonitoring.INSTANCE.stopTracing(trace, attrs); | ||
| } catch (Exception e) { | ||
| Logger.exception("Failed to stop tracing ", e); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@avazirna Can we abstract this function in some util as code is getting repeated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, great point
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Product Description
This PR is the first in a series related to the retirement of
CommCareSessionService. One of the options is to encrypt files using Android keystore facilities. To ensure that this change won't negatively impact CommCare performance, we decided to start measuring files encryption times to better assess this impact.Ticket: https://dimagi.atlassian.net/browse/SAAS-19065
Original PR: #3490
Safety Assurance
Safety story
This was designed to be a null-safe operation and has no impact to the user.
Labels and Review