Allow multiple message latency percentiles.

This commit is contained in:
Clark
2024-01-23 11:34:22 -05:00
committed by Greyson Parrelli
parent 96823e944d
commit 653914f47e

View File

@@ -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<LocalMetricsDatabase.EventMetrics>, minimumEventAgeMs: Long, percentage: Int, messageThreshold: Int, durationThreshold: Long): Boolean {
private fun hasLongMessageLatency(metrics: List<LocalMetricsDatabase.EventMetrics>, minimumEventAgeMs: Long, messageThreshold: Int, percentiles: Map<Int, Long>): 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<Int, Long>
)