From 653914f47e1fd53823e2a5e17018a84428831b70 Mon Sep 17 00:00:00 2001 From: Clark Date: Tue, 23 Jan 2024 11:34:22 -0500 Subject: [PATCH] Allow multiple message latency percentiles. --- .../SlowNotificationHeuristics.kt | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/SlowNotificationHeuristics.kt b/app/src/main/java/org/thoughtcrime/securesms/notifications/SlowNotificationHeuristics.kt index 28182db88c..87dfc946b2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/SlowNotificationHeuristics.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/SlowNotificationHeuristics.kt @@ -21,6 +21,7 @@ import org.thoughtcrime.securesms.util.SignalLocalMetrics import java.util.concurrent.TimeUnit import kotlin.time.Duration.Companion.days import kotlin.time.Duration.Companion.hours +import kotlin.time.Duration.Companion.minutes /** * Heuristic for estimating if a user has been experiencing issues with delayed notifications. @@ -52,10 +53,12 @@ object SlowNotificationHeuristics { minimumEventAgeMs = 3.days.inWholeMilliseconds, minimumServiceEventCount = 10, serviceStartFailurePercentage = 0.5f, - messageLatencyPercentage = 75, - messageLatencyThreshold = 6.hours.inWholeMilliseconds, minimumMessageLatencyEvents = 50, - weeklyFailedQueueDrains = 5 + weeklyFailedQueueDrains = 5, + messageLatencyPercentiles = mapOf( + 90 to 2.hours.inWholeMilliseconds, + 50 to 30.minutes.inWholeMilliseconds + ) ) } @@ -102,7 +105,7 @@ object SlowNotificationHeuristics { val failedServiceStarts = hasRepeatedFailedServiceStarts(metrics, configuration.minimumEventAgeMs, configuration.minimumServiceEventCount, configuration.serviceStartFailurePercentage) val failedQueueDrains = isFailingToDrainQueue(metrics, configuration.minimumEventAgeMs, configuration.weeklyFailedQueueDrains) - val longMessageLatency = hasLongMessageLatency(metrics, configuration.minimumEventAgeMs, configuration.messageLatencyPercentage, configuration.minimumMessageLatencyEvents, configuration.messageLatencyThreshold) + val longMessageLatency = hasLongMessageLatency(metrics, configuration.minimumEventAgeMs, configuration.minimumMessageLatencyEvents, configuration.messageLatencyPercentiles) if (failedServiceStarts || failedQueueDrains || longMessageLatency) { Log.w(TAG, "User seems to be having delayed notifications: failed-service-starts=$failedServiceStarts failedQueueDrains=$failedQueueDrains longMessageLatency=$longMessageLatency") @@ -171,7 +174,7 @@ object SlowNotificationHeuristics { return true } - private fun hasLongMessageLatency(metrics: List, minimumEventAgeMs: Long, percentage: Int, messageThreshold: Int, durationThreshold: Long): Boolean { + private fun hasLongMessageLatency(metrics: List, minimumEventAgeMs: Long, messageThreshold: Int, percentiles: Map): Boolean { if (!haveEnoughData(SignalLocalMetrics.MessageLatency.NAME_HIGH, minimumEventAgeMs)) { Log.d(TAG, "insufficient data for message latency") return false @@ -182,13 +185,15 @@ object SlowNotificationHeuristics { return false } val db = LocalMetricsDatabase.getInstance(ApplicationDependencies.getApplication()) - val averageLatency = db.eventPercent(SignalLocalMetrics.MessageLatency.NAME_HIGH, percentage.coerceAtMost(100).coerceAtLeast(0)) + for ((percentage, threshold) in percentiles.entries) { + val averageLatency = db.eventPercent(SignalLocalMetrics.MessageLatency.NAME_HIGH, percentage.coerceAtMost(100).coerceAtLeast(0)) - val longMessageLatency = averageLatency > durationThreshold - if (longMessageLatency) { - Log.w(TAG, "User has high average message latency of $averageLatency ms over $eventCount events") + if (averageLatency > threshold) { + Log.w(TAG, "User has high average message latency of $averageLatency ms over $eventCount events over threshold of $threshold ms") + return true + } } - return longMessageLatency + return false } private fun haveEnoughData(eventName: String, minimumEventAgeMs: Long): Boolean { @@ -206,6 +211,5 @@ data class Configuration( val serviceStartFailurePercentage: Float, val weeklyFailedQueueDrains: Int, val minimumMessageLatencyEvents: Int, - val messageLatencyThreshold: Long, - val messageLatencyPercentage: Int + val messageLatencyPercentiles: Map )