first portion of metrics

This commit is contained in:
Martin Ptáček
2023-07-30 07:43:49 +02:00
parent 160134b1d2
commit 11c07e4095
6 changed files with 142 additions and 44 deletions

View File

@ -74,4 +74,9 @@ $ ansible-playbook ansible_playbook.yaml --tags config
## List of exported metrics: ## List of exported metrics:
TODO: add grafana dashboard json here `android_battery_charge_ratio` - Current battery charge
`android_system_info{manufacturer, model, os_release, cpu_core_count}` - Information about Android system
`android_uptime_seconds` - Phone uptime in seconds
`android_cpu_active_seconds{core}` - Active CPU time in seconds since last time system booted
`android_cpu_total_seconds{core}` - Total CPU time in seconds since last time system booted
`android_system_temperature_celsius{where}` - Temperature on the device

View File

@ -7,6 +7,7 @@
<option name="testRunner" value="GRADLE" /> <option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" /> <option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="jbr-17" />
<option name="modules"> <option name="modules">
<set> <set>
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />

View File

@ -8,6 +8,8 @@
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" /> <uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.DEVICE_POWER"/>
<application <application
android:allowBackup="true" android:allowBackup="true"

View File

@ -2,8 +2,10 @@
package com.birdthedeveloper.prometheus.android.exporter.worker package com.birdthedeveloper.prometheus.android.exporter.worker
import android.os.CpuUsageInfo
import android.util.Log import android.util.Log
import io.prometheus.client.Collector import io.prometheus.client.Collector
import io.prometheus.client.Gauge
import io.prometheus.client.GaugeMetricFamily import io.prometheus.client.GaugeMetricFamily
private const val TAG = "ANDROID_EXPORTER" private const val TAG = "ANDROID_EXPORTER"
@ -15,32 +17,23 @@ class AndroidCustomExporter(private val metricEngine: MetricsEngine) : Collector
val mfs: MutableList<MetricFamilySamples> = ArrayList() val mfs: MutableList<MetricFamilySamples> = ArrayList()
//TODO scrape_duration gauge //TODO scrape_duration gauge
val startTime = System.currentTimeMillis()
// metrics definitions // metrics definitions
// collectBatteryStatus(mfs) collectBatteryChargeRatio(mfs)
// collectGps(mfs) collectUptimeInSeconds(mfs)
collectSteps(mfs) // collectCpuUsage(mfs)
collectHasWiFiConnection(mfs)
collectHasCellularConnection(mfs)
// collectDeviceTemperatures(mfs)
collectAndroidInfo(mfs)
collectScrapeDuration(mfs, startTime)
Log.d(TAG, "Metrics collected") Log.d(TAG, "Metrics collected")
return mfs return mfs
} }
// private fun collectBatteryStatus(mfs: MutableList<MetricFamilySamples>) {
// //TODO
// val batteryPercentageGauge = GaugeMetricFamily(
// "battery_percentage", //TODO convert to ratio
// "Current battery percentage", listOf(),
// )
//
// val batteryPercentage: Double = metricsEngineRef.batteryChargeRatio().toDouble()
// batteryPercentageGauge.addMetric(listOf(), batteryPercentage)
// mfs.add(batteryPercentageGauge)
// }
// private fun collectGps(mfs: MutableList<MetricFamilySamples>){
// //TODO
// }
private fun collectSteps(mfs: MutableList<MetricFamilySamples>){ private fun collectSteps(mfs: MutableList<MetricFamilySamples>){
val gauge = GaugeMetricFamily( val gauge = GaugeMetricFamily(
"steps", "steps",
@ -50,4 +43,110 @@ class AndroidCustomExporter(private val metricEngine: MetricsEngine) : Collector
gauge.addMetric(listOf(), 1.0) gauge.addMetric(listOf(), 1.0)
mfs.add(gauge) mfs.add(gauge)
} }
private fun collectBatteryChargeRatio(mfs : MutableList<MetricFamilySamples>){
val gauge = GaugeMetricFamily(
"android_battery_charge_ratio",
"Current battery charge",
listOf(),
)
gauge.addMetric(listOf(), metricEngine.getBatteryChargeRatio())
mfs.add(gauge)
}
private fun collectUptimeInSeconds(mfs : MutableList<MetricFamilySamples>){
val gauge = GaugeMetricFamily(
"android_uptime_seconds",
"Android uptime in seconds",
listOf(),
)
gauge.addMetric(listOf(), metricEngine.getUptimeInSeconds())
mfs.add(gauge)
}
//TODO this does not work
private fun collectCpuUsage(mfs : MutableList<MetricFamilySamples>){
var coreIndex= 0
val cpuUsage : Array<CpuUsageInfo> = metricEngine.getCpuUsage()
val gaugeActive = GaugeMetricFamily(
"android_cpu_active_seconds",
"Active CPU time in seconds since last system booted",
listOf("core"),
)
val gaugeTotal = GaugeMetricFamily(
"android_cpu_total_seconds",
"Total CPU time in seconds since last system booted",
listOf("core")
)
cpuUsage.forEach {
gaugeActive.addMetric(listOf((coreIndex++).toString()), it.active / 1000.0)
gaugeActive.addMetric(listOf((coreIndex++).toString()), it.total / 1000.0)
}
mfs.addAll(listOf(gaugeTotal, gaugeActive))
}
//TODO does not work
private fun collectDeviceTemperatures(mfs : MutableList<MetricFamilySamples>){
val deviceTemperatures = metricEngine.getDeviceTemperatures()
val gauge = GaugeMetricFamily(
"android_system_temperature_celsius{where}` - ",
"Temperature on the device",
listOf("where")
)
deviceTemperatures.entries.forEach{
gauge.addMetric(listOf(it.key), it.value)
}
mfs.add(gauge)
}
private fun collectHasWiFiConnection(mfs : MutableList<MetricFamilySamples>){
}
private fun collectHasCellularConnection(mfs : MutableList<MetricFamilySamples>){
}
private fun collectAndroidInfo(mfs : MutableList<MetricFamilySamples>){
val gauge = GaugeMetricFamily(
"android_system_info",
"Static information about the android phone",
listOf("manufacturer", "model", "os_release","cpu_core_count")
)
gauge.addMetric(listOf(
metricEngine.getAndroidManufacturer(),
metricEngine.getAndroidModel(),
metricEngine.getAndroidOsVersion(),
metricEngine.getNumberOfCpuCores().toString(),
), 1.0)
mfs.add(gauge)
}
private fun collectNumberOfCpuCores(mfs : MutableList<MetricFamilySamples>){
val gauge = GaugeMetricFamily(
"android_system_info",
"Static information about the android phone",
listOf("manufacturer", "model", "os_release",)
)
gauge.addMetric(listOf(
metricEngine.getAndroidManufacturer(),
metricEngine.getAndroidModel(),
metricEngine.getAndroidOsVersion(),
), 1.0)
mfs.add(gauge)
}
private fun collectScrapeDuration(mfs : MutableList<MetricFamilySamples>, startTime : Long){
val gauge = GaugeMetricFamily(
"android_scrape_duration_seconds",
"Duration of the metric scrape",
listOf()
)
val differenceMilis = System.currentTimeMillis() - startTime
gauge.addMetric(listOf(), differenceMilis / 1000.0)
mfs.add(gauge)
}
} }

View File

@ -27,10 +27,6 @@ data class AxisSpecificGauge(
) )
class HwSensorsCache( class HwSensorsCache(
var batteryChargeRatio : Double? = null,
var numberOfSteps : Int? = null,
var headingDegrees : Double? = null, var headingDegrees : Double? = null,
var headingAccuracyDegrees : Double? = null, var headingAccuracyDegrees : Double? = null,
var hingeAngleDegrees : Double? = null, var hingeAngleDegrees : Double? = null,
@ -83,11 +79,10 @@ val temperatureTypes : Map<Int, String> = mapOf(
class MetricsEngine(private val context: Context) : SensorEventListener { class MetricsEngine(private val context: Context) : SensorEventListener {
private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
private val hwSensorsCache = HwSensorsCache() private val hwSensorsCache = HwSensorsCache()
val hwPropertiesManager = context.getSystemService(Context.HARDWARE_PROPERTIES_SERVICE) as HardwarePropertiesManager private val hwPropertiesManager = context.getSystemService(Context.HARDWARE_PROPERTIES_SERVICE) as HardwarePropertiesManager
init { init {
//TODO registerAllHwEventHandlers()
//registerAllHwEventHandlers()
} }
fun hwSensorsValues(): HwSensorsCache { fun hwSensorsValues(): HwSensorsCache {
@ -108,7 +103,7 @@ class MetricsEngine(private val context: Context) : SensorEventListener {
} }
fun dispose() { fun dispose() {
//sensorManager.unregisterListener(this) sensorManager.unregisterListener(this)
} }
override fun onSensorChanged(event: SensorEvent?) { override fun onSensorChanged(event: SensorEvent?) {
@ -193,15 +188,7 @@ class MetricsEngine(private val context: Context) : SensorEventListener {
// Do nothing // Do nothing
} }
fun getBatteryChargeRatio(): Double {
// - network availability
// - 4G, 5G
// - ram
// - scrape duration
// - bluetooth - mac bluetooth
// - storage information
fun batteryChargeRatio(): Float {
val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { intFilter -> val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { intFilter ->
context.registerReceiver(null, intFilter) context.registerReceiver(null, intFilter)
} }
@ -213,8 +200,8 @@ class MetricsEngine(private val context: Context) : SensorEventListener {
level / scale.toFloat() level / scale.toFloat()
} }
batteryRatio ?: return -1.0f batteryRatio ?: return -1.0
return batteryRatio return batteryRatio.toDouble()
} }
fun getNumberOfCpuCores(): Int { fun getNumberOfCpuCores(): Int {
@ -225,7 +212,7 @@ class MetricsEngine(private val context: Context) : SensorEventListener {
return SystemClock.elapsedRealtime() / 1000.0 return SystemClock.elapsedRealtime() / 1000.0
} }
fun cpuUsage() : Array<CpuUsageInfo> { fun getCpuUsage() : Array<CpuUsageInfo> {
return hwPropertiesManager.cpuUsages return hwPropertiesManager.cpuUsages
} }
@ -255,7 +242,11 @@ class MetricsEngine(private val context: Context) : SensorEventListener {
return Build.MANUFACTURER return Build.MANUFACTURER
} }
//TODO has_celular fun getHasCellularConnected() : Boolean {
//TODO has_wifi TODO()
//TODO prefix metrics with exporter name - android_ ... }
fun getHasWiFiConnected() : Boolean {
TODO()
}
} }

View File

@ -2,7 +2,7 @@
# Prometheus global configuration file # Prometheus global configuration file
global: global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. scrape_interval: 5s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
scrape_configs: scrape_configs:
- job_name: "prometheus" - job_name: "prometheus"