mirror of
https://github.com/mii443/prometheus-android-exporter.git
synced 2025-08-22 15:15:35 +00:00
final
This commit is contained in:
@ -43,7 +43,8 @@ data class PromConfigFile(
|
||||
?: defaultRemoteWriteMaxSamplesPerExport).toString(),
|
||||
remoteWriteExportInterval = (this.remote_write?.export_interval
|
||||
?: defaultRemoteWriteExportInterval).toString(),
|
||||
remoteWriteInstanceLabel = this.remote_write?.instance ?: defaultRemoteWriteInstanceLabel,
|
||||
remoteWriteInstanceLabel = this.remote_write?.instance
|
||||
?: defaultRemoteWriteInstanceLabel,
|
||||
remoteWriteJobLabel = this.remote_write?.job ?: defaultRemoteWriteJobLabel,
|
||||
)
|
||||
}
|
||||
@ -112,7 +113,7 @@ data class PromConfiguration(
|
||||
}
|
||||
|
||||
companion object {
|
||||
// data/user/0/com.birdthedeveloper.prometheus.android.exporter/files
|
||||
// data/user/0/com.birdthedeveloper.prometheus.android.exporter/files/
|
||||
private const val filename: String = "config.yaml"
|
||||
private const val alternativeFilename: String = "config.yml"
|
||||
fun configFileExists(context: Context): Boolean {
|
||||
|
@ -252,6 +252,13 @@ class PromViewModel : ViewModel() {
|
||||
"Scrape interval must be smaller than Export interval!"
|
||||
)
|
||||
}
|
||||
|
||||
// check target labels
|
||||
if (config.remoteWriteInstanceLabel.isEmpty() || config.remoteWriteJobLabel.isEmpty()) {
|
||||
return displayConfigValidationDialog(
|
||||
"Job target label and Instance target label must be set!"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// validate settings for prometheus server
|
||||
|
@ -38,8 +38,15 @@ fun SettingsPage(
|
||||
}
|
||||
)
|
||||
|
||||
Text( modifier = Modifier.padding(all = 20.dp),
|
||||
text = "This application is licensed under the Apache 2.0 license.", textAlign = TextAlign.Center,)
|
||||
Text(modifier = Modifier.padding(all = 20.dp),text = "Author: Martin Ptacek, 2023", textAlign = TextAlign.Center,)
|
||||
Text(
|
||||
modifier = Modifier.padding(all = 20.dp),
|
||||
text = "This application is licensed under the Apache 2.0 license.",
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.padding(all = 20.dp),
|
||||
text = "Author: Martin Ptacek, 2023",
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -2,10 +2,8 @@
|
||||
|
||||
package com.birdthedeveloper.prometheus.android.exporter.worker
|
||||
|
||||
import android.os.CpuUsageInfo
|
||||
import android.util.Log
|
||||
import io.prometheus.client.Collector
|
||||
import io.prometheus.client.Gauge
|
||||
import io.prometheus.client.GaugeMetricFamily
|
||||
|
||||
private const val TAG = "ANDROID_EXPORTER"
|
||||
@ -112,12 +110,14 @@ class AndroidCustomExporter(private val metricEngine: MetricsEngine) : Collector
|
||||
"Static information about the android phone",
|
||||
listOf("manufacturer", "model", "os_release", "cpu_core_count")
|
||||
)
|
||||
gauge.addMetric(listOf(
|
||||
gauge.addMetric(
|
||||
listOf(
|
||||
metricEngine.getAndroidManufacturer(),
|
||||
metricEngine.getAndroidModel(),
|
||||
metricEngine.getAndroidOsVersion(),
|
||||
metricEngine.getNumberOfCpuCores().toString(),
|
||||
), 1.0)
|
||||
), 1.0
|
||||
)
|
||||
mfs.add(gauge)
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,8 @@ val temperatureTypes : Map<Int, String> = mapOf(
|
||||
class MetricsEngine(private val context: Context) : SensorEventListener {
|
||||
private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||
private val hwSensorsCache = HwSensorsCache()
|
||||
private val hwPropertiesManager = context.getSystemService(Context.HARDWARE_PROPERTIES_SERVICE) as HardwarePropertiesManager
|
||||
private val hwPropertiesManager =
|
||||
context.getSystemService(Context.HARDWARE_PROPERTIES_SERVICE) as HardwarePropertiesManager
|
||||
|
||||
init {
|
||||
registerAllHwEventHandlers()
|
||||
@ -204,7 +205,6 @@ class MetricsEngine(private val context: Context) : SensorEventListener {
|
||||
return batteryRatio.toDouble()
|
||||
}
|
||||
|
||||
//TODO
|
||||
fun getBatteryIsCharging(): Boolean {
|
||||
val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { intFilter ->
|
||||
context.registerReceiver(null, intFilter)
|
||||
@ -259,7 +259,9 @@ class MetricsEngine(private val context: Context) : SensorEventListener {
|
||||
val network = connectivityManager.activeNetwork
|
||||
val cap = connectivityManager.getNetworkCapabilities(network)
|
||||
|
||||
cap != null && (cap.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || cap.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE))
|
||||
cap != null && (cap.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || cap.hasTransport(
|
||||
NetworkCapabilities.TRANSPORT_WIFI_AWARE
|
||||
))
|
||||
|
||||
} else {
|
||||
null
|
||||
|
@ -7,7 +7,6 @@ import android.util.Log
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.engine.android.Android
|
||||
import io.ktor.client.engine.cio.CIO
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.request
|
||||
import io.ktor.client.request.setBody
|
||||
|
@ -87,7 +87,8 @@ data class RemoteWriteConfiguration(
|
||||
|
||||
class RemoteWriteSender(private val config: RemoteWriteConfiguration) {
|
||||
private val lastTimeRingBuffer = LastTimeRingBuffer(config.scrapeInterval)
|
||||
private val storage: RemoteWriteSenderStorage = RemoteWriteSenderSimpleMemoryStorage(config.targetLabels)
|
||||
private val storage: RemoteWriteSenderStorage =
|
||||
RemoteWriteSenderSimpleMemoryStorage(config.targetLabels)
|
||||
private var scrapesAreBeingSent: Boolean = false
|
||||
private lateinit var client: HttpClient
|
||||
private var lastTimeRemoteWriteSent: Long = 0
|
||||
|
@ -12,10 +12,12 @@ private typealias ConverterHashMap = HashMap<List<TimeSeriesLabel>, MutableList<
|
||||
|
||||
private const val TAG: String = "REMOTE_WRITE_SENDER_MEMORY_SIMPLE_STORAGE"
|
||||
|
||||
class RemoteWriteSenderSimpleMemoryStorage(val targetLabels: Map<String, String>) : RemoteWriteSenderStorage() {
|
||||
class RemoteWriteSenderSimpleMemoryStorage(val targetLabels: Map<String, String>) :
|
||||
RemoteWriteSenderStorage() {
|
||||
private val data: Queue<MetricsScrape> = LinkedList()
|
||||
|
||||
private fun filterExpiredMetrics(metrics: MutableList<MetricsScrape>) {
|
||||
companion object {
|
||||
fun filterExpiredMetrics(metrics: MutableList<MetricsScrape>) {
|
||||
val now: Long = System.currentTimeMillis()
|
||||
val oldestMetricTimeMs: Long = now - maxMetricsAge * 1000
|
||||
var howManyMetricsRemove = 0
|
||||
@ -37,6 +39,7 @@ class RemoteWriteSenderSimpleMemoryStorage(val targetLabels: Map<String, String>
|
||||
metrics.removeFirst()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun hashMapEntryToProtobufTimeSeries(
|
||||
labels: List<TimeSeriesLabel>, samples: MutableList<TimeSeriesSample>
|
||||
|
@ -1,3 +1,5 @@
|
||||
// Author: Martin Ptacek
|
||||
|
||||
package com.birdthedeveloper.prometheus.android.exporter.worker
|
||||
|
||||
import org.junit.Assert
|
||||
|
@ -1,41 +1,43 @@
|
||||
// Author: Martin Ptacek
|
||||
|
||||
package com.birdthedeveloper.prometheus.android.exporter.worker
|
||||
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class RemoteWriteSenderStorageTest {
|
||||
// @Test
|
||||
// fun `basic test filterExpiredMetrics`(){
|
||||
// val metrics : MutableList<MetricsScrape> = mutableListOf(
|
||||
// // MetricSamples must be ordered
|
||||
// createDummyMetricsScrape(70),
|
||||
// createDummyMetricsScrape(50),
|
||||
// createDummyMetricsScrape(30),
|
||||
// )
|
||||
//
|
||||
// // execute SUT
|
||||
// RemoteWriteSenderStorage.filterExpiredMetrics(metrics)
|
||||
//
|
||||
// assertEquals(2, metrics.size)
|
||||
//
|
||||
// // assert the right order
|
||||
// val firstTimeStamp = metrics[0].timeSeriesList[0].sample.timeStampMs
|
||||
// val secondTimeStamp = metrics[1].timeSeriesList[0].sample.timeStampMs
|
||||
// assertTrue(firstTimeStamp < secondTimeStamp)
|
||||
// }
|
||||
@Test
|
||||
fun `basic test filterExpiredMetrics`() {
|
||||
val metrics: MutableList<MetricsScrape> = mutableListOf(
|
||||
// MetricSamples must be ordered
|
||||
createDummyMetricsScrape(70),
|
||||
createDummyMetricsScrape(50),
|
||||
createDummyMetricsScrape(30),
|
||||
)
|
||||
|
||||
// private fun createDummyMetricsScrape(ageInMinutes : Int) : MetricsScrape{
|
||||
// return MetricsScrape(
|
||||
// timeSeriesList = listOf(
|
||||
// StorageTimeSeries(
|
||||
// labels = listOf(),
|
||||
// sample = TimeSeriesSample(
|
||||
// // too old
|
||||
// timeStampMs = System.currentTimeMillis() - ageInMinutes * 60 * 1000L,
|
||||
// value = 0.0,
|
||||
// ),
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
RemoteWriteSenderSimpleMemoryStorage.filterExpiredMetrics(metrics)
|
||||
|
||||
assertEquals(2, metrics.size)
|
||||
|
||||
// assert the right order
|
||||
val firstTimeStamp = metrics[0].timeSeriesList[0].sample.timeStampMs
|
||||
val secondTimeStamp = metrics[1].timeSeriesList[0].sample.timeStampMs
|
||||
assertTrue(firstTimeStamp < secondTimeStamp)
|
||||
}
|
||||
|
||||
private fun createDummyMetricsScrape(ageInMinutes: Int): MetricsScrape {
|
||||
return MetricsScrape(
|
||||
timeSeriesList = listOf(
|
||||
StorageTimeSeries(
|
||||
labels = listOf(),
|
||||
sample = TimeSeriesSample(
|
||||
// too old
|
||||
timeStampMs = System.currentTimeMillis() - ageInMinutes * 60 * 1000L,
|
||||
value = 0.0,
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user