All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.pubnub.api.managers.TelemetryManager.kt Maven / Gradle / Ivy

Go to download

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!

There is a newer version: 10.2.0
Show newest version
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
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy