com.pubnub.api.managers.TelemetryManager.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pubnub-kotlin Show documentation
Show all versions of pubnub-kotlin Show documentation
PubNub is a cross-platform client-to-client (1:1 and 1:many) push service in the cloud, capable of
broadcasting real-time messages to millions of web and mobile clients simultaneously, in less than a quarter
second!
package com.pubnub.api.managers
import com.pubnub.api.enums.PNOperationType
import java.math.RoundingMode
import java.text.NumberFormat
import java.util.Date
import java.util.Locale
import kotlin.collections.set
class TelemetryManager {
private companion object {
private const val MAX_FRACTION_DIGITS = 3
private const val TIMESTAMP_DIVIDER = 1_000
private const val MAXIMUM_LATENCY_DATA_AGE = 60.0
}
private val latencies: HashMap> = HashMap()
private val numberFormat by lazy {
NumberFormat.getNumberInstance(Locale.US).apply {
maximumFractionDigits = MAX_FRACTION_DIGITS
roundingMode = RoundingMode.HALF_UP
isGroupingUsed = false
}
}
@Synchronized
internal fun operationsLatency(currentDate: Long = Date().time): Map {
cleanUpTelemetryData(currentDate)
val operationLatencies = HashMap()
latencies.entries.forEach {
val latencyKey = "l_${it.key}"
val endpointAverageLatency = averageLatencyFromData(it.value)
if (endpointAverageLatency > 0.0f) {
operationLatencies[latencyKey] = numberFormat.format(endpointAverageLatency)
}
}
return operationLatencies
}
@Synchronized
private fun cleanUpTelemetryData(currentDate: Long = Date().time) {
val date = currentDate / TIMESTAMP_DIVIDER.toDouble()
// remove outdated latencies
latencies.forEach { (_, operationLatencies) ->
val outdated = operationLatencies.filter { it.isOutdated(date) }
operationLatencies -= outdated
}
// remove empty latency list
latencies.filterValues { it.isNullOrEmpty() }
.forEach { (endpoint, _) ->
latencies -= endpoint
}
}
private fun averageLatencyFromData(endpointLatencies: List): Double {
val sumOfLatencies = endpointLatencies.sumOf { it.latency }
return sumOfLatencies / endpointLatencies.size
}
@Synchronized
internal fun storeLatency(latency: Long, type: PNOperationType, currentDate: Long = Date().time) {
type.queryParam?.let { queryParam: String ->
if (latency > 0) {
val storeDate = currentDate / (TIMESTAMP_DIVIDER.toDouble())
if (latencies[queryParam] == null) {
latencies[queryParam] = ArrayList()
}
latencies[queryParam]?.let {
val latencyEntry = Latency(
date = storeDate,
latency = latency.toDouble() / TIMESTAMP_DIVIDER
)
it.add(latencyEntry)
}
}
}
}
private data class Latency(val latency: Double, val date: Double) {
fun isOutdated(currentDate: Double) = currentDate - date > MAXIMUM_LATENCY_DATA_AGE
}
}