mirror of
https://github.com/mii443/prometheus-android-exporter.git
synced 2025-08-22 15:15:35 +00:00
wip logging
This commit is contained in:
@ -11,7 +11,6 @@ import java.io.File
|
||||
|
||||
private const val TAG: String = "CONFIGURATION"
|
||||
|
||||
//TODO register within prometheus foundation
|
||||
private const val defaultPrometheusServerPort: Int = 10101
|
||||
private const val defaultRemoteWriteScrapeInterval: Int = 30 // seconds
|
||||
private const val defaultRemoteWriteMaxSamplesPerExport: Int = 60 // seconds
|
||||
@ -118,7 +117,7 @@ data class PromConfiguration(
|
||||
}
|
||||
|
||||
fun loadFromConfigFile(context: Context): PromConfiguration {
|
||||
Log.v(TAG, context.filesDir.absolutePath)
|
||||
Log.d(TAG, "Loading configuration file now")
|
||||
|
||||
val file = File(context.filesDir, filename)
|
||||
val alternativeFile = File(context.filesDir, alternativeFilename)
|
||||
@ -135,7 +134,7 @@ data class PromConfiguration(
|
||||
fileContents
|
||||
)
|
||||
|
||||
Log.v(TAG, parsedConfig.prometheus_server?.port.toString())
|
||||
Log.d(TAG, "Configuration file loaded")
|
||||
|
||||
return parsedConfig.toPromConfiguration()
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavHostController
|
||||
|
||||
private val TAG = "HOMEPAGE"
|
||||
private const val TAG : String = "HOMEPAGE"
|
||||
|
||||
@Composable
|
||||
fun HomePage(
|
||||
@ -206,13 +206,14 @@ private fun PrometheusServerPage(
|
||||
) {
|
||||
|
||||
TextField(
|
||||
value = uiState.promConfig.prometheusServerPort.toString(),
|
||||
value = uiState.promConfig.prometheusServerPort,
|
||||
singleLine = true,
|
||||
onValueChange = {
|
||||
promViewModel.updatePromConfig(UpdatePromConfig.PrometheusServerPort, it)
|
||||
},
|
||||
label = { Text("Prometheus HTTP port") },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
enabled = uiState.exporterState == ExporterState.NotRunning,
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
@ -226,7 +227,8 @@ private fun PrometheusServerPage(
|
||||
if (value != null) {
|
||||
promViewModel.updatePromConfig(UpdatePromConfig.PrometheusServerEnabled, value)
|
||||
}
|
||||
}
|
||||
},
|
||||
enabled = uiState.exporterState == ExporterState.NotRunning,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -260,7 +262,8 @@ private fun PushProxPage(
|
||||
label = {
|
||||
Text(text = "Fully Qualified Domain Name")
|
||||
},
|
||||
modifier = Modifier.padding(bottom = 12.dp)
|
||||
modifier = Modifier.padding(bottom = 12.dp),
|
||||
enabled = uiState.exporterState == ExporterState.NotRunning,
|
||||
)
|
||||
|
||||
TextField(
|
||||
@ -272,6 +275,7 @@ private fun PushProxPage(
|
||||
label = {
|
||||
Text(text = "PushProx proxy URL")
|
||||
},
|
||||
enabled = uiState.exporterState == ExporterState.NotRunning,
|
||||
)
|
||||
|
||||
Switch(
|
||||
@ -280,7 +284,8 @@ private fun PushProxPage(
|
||||
if (value != null) {
|
||||
promViewModel.updatePromConfig(UpdatePromConfig.PushproxEnabled, value)
|
||||
}
|
||||
}
|
||||
},
|
||||
enabled = uiState.exporterState == ExporterState.NotRunning,
|
||||
)
|
||||
|
||||
}
|
||||
@ -310,7 +315,8 @@ private fun RemoteWritePage(
|
||||
label = {
|
||||
Text(text = "Remote write endpoint")
|
||||
},
|
||||
modifier = Modifier.padding(bottom = 12.dp)
|
||||
modifier = Modifier.padding(bottom = 12.dp),
|
||||
enabled = uiState.exporterState == ExporterState.NotRunning,
|
||||
)
|
||||
|
||||
TextField(
|
||||
@ -323,6 +329,7 @@ private fun RemoteWritePage(
|
||||
label = {
|
||||
Text(text = "Scrape interval in seconds")
|
||||
},
|
||||
enabled = uiState.exporterState == ExporterState.NotRunning,
|
||||
)
|
||||
|
||||
TextField(
|
||||
@ -335,6 +342,7 @@ private fun RemoteWritePage(
|
||||
label = {
|
||||
Text(text = "Max number of samples per export")
|
||||
},
|
||||
enabled = uiState.exporterState == ExporterState.NotRunning,
|
||||
)
|
||||
|
||||
TextField(
|
||||
@ -347,6 +355,7 @@ private fun RemoteWritePage(
|
||||
label = {
|
||||
Text(text = "Export interval in seconds")
|
||||
},
|
||||
enabled = uiState.exporterState == ExporterState.NotRunning,
|
||||
)
|
||||
|
||||
Switch(
|
||||
@ -355,7 +364,8 @@ private fun RemoteWritePage(
|
||||
if (value != null) {
|
||||
promViewModel.updatePromConfig(UpdatePromConfig.RemoteWriteEnabled, value)
|
||||
}
|
||||
}
|
||||
},
|
||||
enabled = uiState.exporterState == ExporterState.NotRunning,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ class PromViewModel : ViewModel() {
|
||||
|
||||
private var workerLiveData: LiveData<List<WorkInfo>>? = null
|
||||
private val workerLiveDataObserver: Observer<List<WorkInfo>> = Observer {
|
||||
Log.d(TAG, "Observing change in worker state")
|
||||
if (it.isEmpty()) {
|
||||
updateExporterStateWith(ExporterState.NotRunning)
|
||||
} else {
|
||||
@ -85,9 +86,8 @@ class PromViewModel : ViewModel() {
|
||||
}
|
||||
|
||||
private fun loadConfigurationFile() {
|
||||
Log.v(TAG, "Checking for configuration file")
|
||||
Log.d(TAG, "Checking for configuration file")
|
||||
|
||||
Log.v(TAG, getContext().filesDir.absolutePath)
|
||||
val fileExists = PromConfiguration.configFileExists(context = getContext())
|
||||
if (fileExists) {
|
||||
val tempPromConfiguration: PromConfiguration
|
||||
@ -101,7 +101,10 @@ class PromViewModel : ViewModel() {
|
||||
)
|
||||
}
|
||||
|
||||
Log.d(TAG, "Configuration file parsed successfully")
|
||||
|
||||
} catch (e: Exception) {
|
||||
Log.d(TAG, "Configuration file parsing failed")
|
||||
_uiState.update { current ->
|
||||
current.copy(
|
||||
configFileState = ConfigFileState.ERROR,
|
||||
@ -202,6 +205,7 @@ class PromViewModel : ViewModel() {
|
||||
}
|
||||
|
||||
private fun validatePromConfiguration(): Boolean {
|
||||
Log.d(TAG, "Validating PromConfiguration now")
|
||||
val config: PromConfiguration = uiState.value.promConfig
|
||||
|
||||
// check either pushprox or prometheus server is turned on
|
||||
@ -244,7 +248,6 @@ class PromViewModel : ViewModel() {
|
||||
"Scrape interval must be smaller than Export interval!"
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// validate settings for prometheus server
|
||||
@ -261,10 +264,12 @@ class PromViewModel : ViewModel() {
|
||||
|
||||
// no need to validate anything for pushprox
|
||||
|
||||
Log.d(TAG, "PromConfiguration validated")
|
||||
return true
|
||||
}
|
||||
|
||||
private fun startWorker() {
|
||||
Log.d(TAG, "Starting worker")
|
||||
if (validatePromConfiguration()) {
|
||||
Log.v(TAG, "Enqueuing work")
|
||||
val workManagerInstance = WorkManager.getInstance(getContext())
|
||||
@ -290,22 +295,13 @@ class PromViewModel : ViewModel() {
|
||||
ExistingWorkPolicy.KEEP,
|
||||
workerRequest,
|
||||
).enqueue()
|
||||
|
||||
// set UI state
|
||||
_uiState.update { current ->
|
||||
current.copy(exporterState = ExporterState.Running)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopWorker() {
|
||||
Log.d(TAG, "Stopping worker")
|
||||
val workerManagerInstance = WorkManager.getInstance(getContext())
|
||||
workerManagerInstance.cancelUniqueWork(PROM_UNIQUE_WORK)
|
||||
|
||||
// update UI state
|
||||
_uiState.update { current ->
|
||||
current.copy(exporterState = ExporterState.NotRunning)
|
||||
}
|
||||
}
|
||||
|
||||
fun updatePromConfig(part: UpdatePromConfig, value: Any) {
|
||||
|
@ -18,8 +18,6 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavHostController
|
||||
|
||||
private val TAG = "SETTINGS_PAGE"
|
||||
|
||||
@Composable
|
||||
fun SettingsPage(
|
||||
promViewModel: PromViewModel,
|
||||
|
@ -4,18 +4,19 @@ import android.util.Log
|
||||
import io.prometheus.client.Collector
|
||||
import io.prometheus.client.GaugeMetricFamily
|
||||
|
||||
private val TAG = "ANDROID_EXPORTER"
|
||||
private const val TAG = "ANDROID_EXPORTER"
|
||||
|
||||
class AndroidCustomExporter(metricEngine: MetricsEngine) : Collector() {
|
||||
private val metricsEngineRef = metricEngine
|
||||
|
||||
override fun collect(): List<MetricFamilySamples> {
|
||||
Log.v(TAG, "collecting")
|
||||
Log.d(TAG, "Collecting metrics now")
|
||||
val mfs: MutableList<MetricFamilySamples> = ArrayList()
|
||||
|
||||
// metrics definitions
|
||||
collectBatteryStatus(mfs)
|
||||
|
||||
Log.d(TAG, "Metrics collected")
|
||||
return mfs
|
||||
}
|
||||
|
||||
|
@ -5,11 +5,10 @@ import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.BatteryManager
|
||||
|
||||
class MetricsEngine(context: Context) {
|
||||
private val contextRef = context
|
||||
class MetricsEngine(private val context: Context) {
|
||||
public fun getBatteryPercentage(): Float {
|
||||
val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { intFilter ->
|
||||
contextRef.registerReceiver(null, intFilter)
|
||||
context.registerReceiver(null, intFilter)
|
||||
}
|
||||
//val status: Int = batteryStatus?.getIntExtra(BatteryManager.EXTRA_STATUS, -1) ?: -1
|
||||
|
||||
|
@ -2,6 +2,7 @@ package com.birdthedeveloper.prometheus.android.prometheus.android.exporter.work
|
||||
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.ForegroundInfo
|
||||
@ -18,20 +19,24 @@ import kotlinx.coroutines.newSingleThreadContext
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.StringWriter
|
||||
|
||||
private const val TAG = "Worker"
|
||||
private const val TAG : String = "Worker"
|
||||
|
||||
class PromWorker(
|
||||
val context: Context,
|
||||
private val context: Context,
|
||||
parameters: WorkerParameters,
|
||||
) : CoroutineWorker(context, parameters) {
|
||||
|
||||
private val collectorRegistry = CollectorRegistry()
|
||||
private val metricsEngine: MetricsEngine = MetricsEngine(context)
|
||||
private val androidCustomExporter: AndroidCustomExporter =
|
||||
AndroidCustomExporter(metricsEngine).register(collectorRegistry)
|
||||
|
||||
private lateinit var pushProxClient: PushProxClient
|
||||
private var remoteWriteSender: RemoteWriteSender? = null
|
||||
|
||||
init {
|
||||
val androidCustomExporter = AndroidCustomExporter(metricsEngine)
|
||||
androidCustomExporter.register<AndroidCustomExporter>(collectorRegistry)
|
||||
}
|
||||
|
||||
//TODO foreground notification
|
||||
private val notificationManager =
|
||||
context.getSystemService(Context.NOTIFICATION_SERVICE) as
|
||||
@ -44,6 +49,7 @@ class PromWorker(
|
||||
}
|
||||
|
||||
private suspend fun countSuccessfulScrape() {
|
||||
Log.d(TAG, "Counting successful scrape")
|
||||
remoteWriteSender?.countSuccessfulScrape()
|
||||
}
|
||||
|
||||
@ -65,12 +71,14 @@ class PromWorker(
|
||||
) { context }
|
||||
)
|
||||
launch {
|
||||
Log.d(TAG, "Remote Write launched")
|
||||
remoteWriteSender?.start()
|
||||
}
|
||||
}
|
||||
|
||||
if (config.prometheusServerEnabled) {
|
||||
launch {
|
||||
Log.d(TAG, "Prometheus server launched")
|
||||
PrometheusServer.start(
|
||||
PrometheusServerConfig(
|
||||
config.prometheusServerPort.toInt(),
|
||||
@ -92,6 +100,7 @@ class PromWorker(
|
||||
)
|
||||
)
|
||||
launch {
|
||||
Log.d(TAG, "PushProx launched")
|
||||
pushProxClient.start()
|
||||
}
|
||||
}
|
||||
|
@ -24,12 +24,11 @@ data class PrometheusServerConfig(
|
||||
val countSuccessfulScrape: suspend () -> Unit,
|
||||
)
|
||||
|
||||
|
||||
// Expose metrics on given port using Ktor http server
|
||||
class PrometheusServer() {
|
||||
companion object {
|
||||
suspend fun start(config: PrometheusServerConfig) {
|
||||
Log.v(TAG, "Starting prometheus server")
|
||||
Log.d(TAG, "Starting prometheus server")
|
||||
|
||||
val server = configureServer(config)
|
||||
|
||||
@ -38,7 +37,7 @@ class PrometheusServer() {
|
||||
delay(Long.MAX_VALUE)
|
||||
} finally {
|
||||
withContext(NonCancellable) {
|
||||
Log.v(TAG, "Canceling Prometheus server")
|
||||
Log.d(TAG, "Canceling Prometheus server")
|
||||
server.stop()
|
||||
}
|
||||
}
|
||||
@ -69,7 +68,6 @@ class PrometheusServer() {
|
||||
}
|
||||
|
||||
private fun configureServer(config: PrometheusServerConfig): ApplicationEngine {
|
||||
//TODO testing of different providers (CIO, netty, jetty ... for performance)
|
||||
return embeddedServer(CIO, port = config.port) {
|
||||
install(StatusPages) {
|
||||
status(HttpStatusCode.NotFound) { call, status ->
|
||||
@ -89,6 +87,7 @@ class PrometheusServer() {
|
||||
get("/metrics") {
|
||||
call.respondText(config.performScrape())
|
||||
config.countSuccessfulScrape()
|
||||
Log.d(TAG, "Successful scrape")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ class PushProxClient(private val pushProxConfig: PushProxConfig) {
|
||||
pushProxConfig.countSuccessfulScrape()
|
||||
} catch (e: Exception) {
|
||||
counters.pushError()
|
||||
Log.v(TAG, "Push exception ${e.toString()}")
|
||||
Log.v(TAG, "Push exception $e")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -83,9 +83,11 @@ class RemoteWriteSender(private val config: RemoteWriteConfiguration) {
|
||||
private var remoteWriteOn: Boolean = false
|
||||
|
||||
private suspend fun performScrapeAndSaveIt(channel: Channel<Unit>) {
|
||||
Log.d(TAG, "performScrapeAndSaveIt start")
|
||||
val scrapedMetrics = config.collectorRegistry.metricFamilySamples()
|
||||
storage.writeScrapedSample(scrapedMetrics)
|
||||
channel.send(Unit)
|
||||
Log.d(TAG, "performScrapeAndSaveIt end")
|
||||
}
|
||||
|
||||
private suspend fun scraper(channel: Channel<Unit>) {
|
||||
@ -106,6 +108,7 @@ class RemoteWriteSender(private val config: RemoteWriteConfiguration) {
|
||||
}
|
||||
|
||||
private suspend fun sendAll() {
|
||||
Log.d(TAG, "sendAll")
|
||||
scrapesAreBeingSent = true
|
||||
while (!storage.isEmpty()) {
|
||||
val body = storage.getScrapedSamplesCompressedProtobuf(config.maxSamplesPerExport)
|
||||
@ -145,7 +148,9 @@ class RemoteWriteSender(private val config: RemoteWriteConfiguration) {
|
||||
if (storage.isEmpty()) {
|
||||
// channel is conflated, one receive is enough
|
||||
// suspend here until sending remote write is needed
|
||||
Log.d(TAG, "Sender manager: waiting on channel receive")
|
||||
channel.receive()
|
||||
Log.d(TAG, "Sender Manager: channel received")
|
||||
}
|
||||
|
||||
while (remoteWriteOn || !storage.isEmpty()) {
|
||||
@ -176,20 +181,20 @@ class RemoteWriteSender(private val config: RemoteWriteConfiguration) {
|
||||
}
|
||||
} finally {
|
||||
withContext(NonCancellable) {
|
||||
Log.d(TAG, "Canceling Remote Write Sender")
|
||||
channel.close()
|
||||
client.close()
|
||||
Log.v(TAG, "Canceling Remote Write Sender")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun countSuccessfulScrape() {
|
||||
Log.v(TAG, "Counting successful scrape")
|
||||
Log.d(TAG, "Counting successful scrape")
|
||||
lastTimeRingBuffer.setLastTime(System.currentTimeMillis())
|
||||
}
|
||||
|
||||
private suspend fun sendRequestToRemoteWrite(body: ByteArray) {
|
||||
Log.v(TAG, "sending to prometheus remote write now")
|
||||
Log.d(TAG, "Exporting remote write to prometheus now")
|
||||
val response = client.post(config.remoteWriteEndpoint) {
|
||||
setBody(body)
|
||||
headers {
|
||||
@ -200,7 +205,6 @@ class RemoteWriteSender(private val config: RemoteWriteConfiguration) {
|
||||
}
|
||||
}
|
||||
|
||||
Log.v(TAG, "Response status: ${response.status}")
|
||||
Log.v(TAG, "body: ${response.body<String>()}")
|
||||
Log.d(TAG, "Response status: ${response.status}")
|
||||
}
|
||||
}
|
||||
|
@ -175,6 +175,7 @@ class RemoteWriteSenderSimpleMemoryStorage : RemoteWriteSenderStorage() {
|
||||
private val data: Queue<MetricsScrape> = LinkedList()
|
||||
|
||||
override fun getScrapedSamplesCompressedProtobuf(howMany: Int): ByteArray {
|
||||
Log.d(TAG, "Getting scraped samples: $howMany samples")
|
||||
if (howMany < 1) {
|
||||
throw IllegalArgumentException("howMany must be bigger than zero")
|
||||
}
|
||||
@ -194,7 +195,9 @@ class RemoteWriteSenderSimpleMemoryStorage : RemoteWriteSenderStorage() {
|
||||
return this.encodeWithSnappy(bytes)
|
||||
}
|
||||
|
||||
//TODO use this thing
|
||||
override fun removeNumberOfScrapedSamples(number: Int) {
|
||||
Log.d(TAG, "Removing number of scraped samples: $number samples")
|
||||
if (number > 0) {
|
||||
for (i in 1..number) {
|
||||
data.remove()
|
||||
@ -205,6 +208,7 @@ class RemoteWriteSenderSimpleMemoryStorage : RemoteWriteSenderStorage() {
|
||||
}
|
||||
|
||||
override fun writeScrapedSample(metricsScrape: MetricsScrape) {
|
||||
Log.d(TAG, "Writing scraped sample to storage")
|
||||
data.add(metricsScrape)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user