From eb9744373aff9be7a8b7f77b078e7b4ca4a734b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Pt=C3=A1=C4=8Dek?= Date: Wed, 31 May 2023 13:37:28 +0200 Subject: [PATCH] remove pushprox worker --- .gitignore | 5 +- README.md | 11 ++ .../android/exporter/compose/PromViewModel.kt | 6 + .../android/exporter/compose/configuration.kt | 19 ++- .../android/exporter/worker/PromWorker.kt | 83 ++++++++++--- .../android/exporter/worker/PushProxWorker.kt | 110 ------------------ config.yaml => config_file_structure.yaml | 16 +-- 7 files changed, 106 insertions(+), 144 deletions(-) delete mode 100644 client/app/src/main/java/com/birdthedeveloper/prometheus/android/prometheus/android/exporter/worker/PushProxWorker.kt rename config.yaml => config_file_structure.yaml (70%) diff --git a/.gitignore b/.gitignore index bbc39b4..8340678 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -credentials/ \ No newline at end of file +credentials/ + +# configuration for working version of Android prometheus exporter +config.yaml diff --git a/README.md b/README.md index be3dac0..251030c 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,17 @@ to run as ROOT. Exposes various hardware sensor metrics. # Client +## File configuration +Client application is configurable via a configuration file. +Place such file on your android device at a following path: +``` +data/user/0/com.birdthedeveloper.prometheus.android.prometheus.android.exporter/files/ +``` +The name of such configuration file can be either `config.yaml` or `config.yml` + +Configurable fields are described in `./config_file_structure.yaml`, all +fields are optional. + ### ADB port forwarding ADB port forwarding is usefull when running the client application on android emulator and prometheus database on the host diff --git a/client/app/src/main/java/com/birdthedeveloper/prometheus/android/prometheus/android/exporter/compose/PromViewModel.kt b/client/app/src/main/java/com/birdthedeveloper/prometheus/android/prometheus/android/exporter/compose/PromViewModel.kt index cb5c11f..88bdfb8 100644 --- a/client/app/src/main/java/com/birdthedeveloper/prometheus/android/prometheus/android/exporter/compose/PromViewModel.kt +++ b/client/app/src/main/java/com/birdthedeveloper/prometheus/android/prometheus/android/exporter/compose/PromViewModel.kt @@ -99,9 +99,15 @@ class PromViewModel(): ViewModel() { when(_uiState.value.exporterState) { ExporterState.Running -> { stopWorker() + _uiState.update { current -> + current.copy(exporterState = ExporterState.NotRunning) + } } ExporterState.NotRunning -> { startWorker() + _uiState.update { current -> + current.copy(exporterState = ExporterState.Running) + } } } } diff --git a/client/app/src/main/java/com/birdthedeveloper/prometheus/android/prometheus/android/exporter/compose/configuration.kt b/client/app/src/main/java/com/birdthedeveloper/prometheus/android/prometheus/android/exporter/compose/configuration.kt index 38097b4..aebfa39 100644 --- a/client/app/src/main/java/com/birdthedeveloper/prometheus/android/prometheus/android/exporter/compose/configuration.kt +++ b/client/app/src/main/java/com/birdthedeveloper/prometheus/android/prometheus/android/exporter/compose/configuration.kt @@ -4,13 +4,10 @@ import android.content.Context import android.util.Log import androidx.work.Data import androidx.work.workDataOf -import com.birdthedeveloper.prometheus.android.prometheus.android.exporter.worker.PushProxConfig import com.charleskorn.kaml.Yaml import kotlinx.serialization.Serializable -import kotlinx.serialization.decodeFromString import java.io.File import kotlinx.serialization.json.Json -import kotlinx.serialization.decodeFromString private const val TAG : String = "CONFIGURATION" @@ -56,6 +53,7 @@ data class RemoteWriteConfigFile( val remote_write_endpoint : String?, ) +// configuration of a work manager worker @Serializable data class PromConfiguration( // the following are default values for various configuration settings @@ -70,7 +68,6 @@ data class PromConfiguration( ) { fun toStructuredText() : String { - //TODO asap return """ prometheus_server: enabled: $prometheusServerEnabled @@ -108,24 +105,22 @@ data class PromConfiguration( val file = File(context.filesDir, filename) val alternativeFile = File(context.filesDir, alternativeFilename) - val fileContents : String - if (file.exists()){ - fileContents = file.readText() + val fileContents : String = if (file.exists()){ + file.readText() }else if (alternativeFile.exists()){ - fileContents = alternativeFile.readText() + alternativeFile.readText() }else{ throw Exception("configuration file does not exist!") } - val parsedYaml : PromConfigFile = Yaml.default.decodeFromString( + val parsedConfig : PromConfigFile = Yaml.default.decodeFromString( PromConfigFile.serializer(), fileContents ) - Log.v(TAG, parsedYaml.prometheus_server?.port.toString()) + Log.v(TAG, parsedConfig.prometheus_server?.port.toString()) - - return parsedYaml.toPromConfiguration() + return parsedConfig.toPromConfiguration() } } diff --git a/client/app/src/main/java/com/birdthedeveloper/prometheus/android/prometheus/android/exporter/worker/PromWorker.kt b/client/app/src/main/java/com/birdthedeveloper/prometheus/android/prometheus/android/exporter/worker/PromWorker.kt index 9b487f8..4609e93 100644 --- a/client/app/src/main/java/com/birdthedeveloper/prometheus/android/prometheus/android/exporter/worker/PromWorker.kt +++ b/client/app/src/main/java/com/birdthedeveloper/prometheus/android/prometheus/android/exporter/worker/PromWorker.kt @@ -1,37 +1,94 @@ package com.birdthedeveloper.prometheus.android.prometheus.android.exporter.worker +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 +import androidx.work.WorkManager import androidx.work.WorkerParameters +import com.birdthedeveloper.prometheus.android.prometheus.android.exporter.R import com.birdthedeveloper.prometheus.android.prometheus.android.exporter.compose.PromConfiguration -import io.ktor.client.HttpClient -import io.ktor.client.engine.cio.CIO -import io.ktor.client.statement.HttpResponse -import kotlinx.coroutines.delay -import java.time.LocalDateTime -import io.ktor.client.request.* +import io.prometheus.client.CollectorRegistry +import io.prometheus.client.exporter.common.TextFormat +import java.io.StringWriter -private val TAG = "Worker" +private const val TAG = "Worker" class PromWorker( context : Context, parameters : WorkerParameters, ) : CoroutineWorker(context, parameters) { + private val collectorRegistry: CollectorRegistry = CollectorRegistry() + private val metricsEngine : MetricsEngine = MetricsEngine(context) + private val pushProxClient = PushProxClient(collectorRegistry, ::performScrape) + private lateinit var androidCustomExporter : AndroidCustomExporter + + //TODO foreground notification + private val notificationManager = + context.getSystemService(Context.NOTIFICATION_SERVICE) as + NotificationManager + + private fun performScrape() : String{ + val writer = StringWriter() + TextFormat.write004(writer, collectorRegistry.metricFamilySamples()) + return writer.toString() + } + + private fun initializeWork(config : PromConfiguration){ + // initialize metrics + androidCustomExporter = AndroidCustomExporter(metricsEngine).register(collectorRegistry) + } + + private fun startServices(config : PromConfiguration){ + if(config.prometheusServerEnabled){ + //DO something + } + + if(config.pushproxEnabled){ + //DO something + } + + if(config.remoteWriteEnabled){ + //DO something + } + } override suspend fun doWork(): Result { val inputConfiguration : PromConfiguration = PromConfiguration.fromWorkData(inputData) - while(true){ - Log.v(TAG, "Worker is working " + LocalDateTime.now().toString()) - //TODO curl localhost + // set foreground - //TODO is this right for the use case? + setForeground(createForegroundInfo()) - delay(1000L) - } + initializeWork(inputConfiguration) + startServices(inputConfiguration) //TODO implement this asap return Result.success() } + //TODO foreground notification + private fun createForegroundInfo(): ForegroundInfo { + val id = "channel_id" + val title = "title" + val cancel = "cancel_download" + // This PendingIntent can be used to cancel the worker + val intent = WorkManager.getInstance(applicationContext) + .createCancelPendingIntent(getId()) + + val notification = NotificationCompat.Builder(applicationContext, id) + .setContentTitle(title) + .setTicker(title) + .setContentText("progress") + .setSmallIcon(R.drawable.ic_launcher_foreground) + .setOngoing(true) + // Add the cancel action to the notification which can + // be used to cancel the worker + .addAction(android.R.drawable.ic_delete, cancel, intent) + .build() + + return ForegroundInfo(1, notification) + } + } \ No newline at end of file diff --git a/client/app/src/main/java/com/birdthedeveloper/prometheus/android/prometheus/android/exporter/worker/PushProxWorker.kt b/client/app/src/main/java/com/birdthedeveloper/prometheus/android/prometheus/android/exporter/worker/PushProxWorker.kt deleted file mode 100644 index 9fb6fca..0000000 --- a/client/app/src/main/java/com/birdthedeveloper/prometheus/android/prometheus/android/exporter/worker/PushProxWorker.kt +++ /dev/null @@ -1,110 +0,0 @@ -package com.birdthedeveloper.prometheus.android.prometheus.android.exporter.worker - -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 -import androidx.work.WorkManager -import androidx.work.WorkerParameters -import com.birdthedeveloper.prometheus.android.prometheus.android.exporter.R -import io.prometheus.client.CollectorRegistry -import io.prometheus.client.exporter.common.TextFormat -import java.io.StringWriter - -private val TAG = "PUSH_PROX_WORKER" - -class PushProxWorker( - private val context : Context, - parameters : WorkerParameters -): CoroutineWorker(context, parameters){ - - private val notificationManager = - context.getSystemService(Context.NOTIFICATION_SERVICE) as - NotificationManager - - override suspend fun doWork():Result { - //TODO implement this - val cache: PushProxWorkerCache = PushProxWorkerCache.getInstance { - return@getInstance context - } - - setForeground(createForegroundInfo()) - - try{ - val pushProxConfig : PushProxConfig = PushProxConfig.fromData(inputData) - - cache.startBackground(pushProxConfig) - - }catch(e : Exception){ - Log.v(TAG, e.toString()) - return Result.failure() - } - - return Result.success() - } - - private fun createForegroundInfo(): ForegroundInfo { - val id = "channel_id" - val title = "title" - val cancel = "cancel_download" - // This PendingIntent can be used to cancel the worker - val intent = WorkManager.getInstance(applicationContext) - .createCancelPendingIntent(getId()) - - val notification = NotificationCompat.Builder(applicationContext, id) - .setContentTitle(title) - .setTicker(title) - .setContentText("progress") - .setSmallIcon(R.drawable.ic_launcher_foreground) - .setOngoing(true) - // Add the cancel action to the notification which can - // be used to cancel the worker - .addAction(android.R.drawable.ic_delete, cancel, intent) - .build() - - return ForegroundInfo(1, notification) - } - -} - -// thread-safe singleton -class PushProxWorkerCache private constructor( - private val getContext: () -> Context -){ - private val collectorRegistry: CollectorRegistry = CollectorRegistry() - private val metricsEngine : MetricsEngine = MetricsEngine(getContext()) - private val pushProxClient = PushProxClient(collectorRegistry, ::performScrape) - private lateinit var androidCustomExporter : AndroidCustomExporter - - init { - Log.v(TAG, "Initializing WorkerCache") - androidCustomExporter = AndroidCustomExporter(metricsEngine).register(collectorRegistry) - } - - private fun performScrape() : String{ - val writer = StringWriter() - TextFormat.write004(writer, collectorRegistry.metricFamilySamples()) - return writer.toString() - } - - suspend fun startBackground(pushProxConfig : PushProxConfig){ - pushProxClient.startBackground(pushProxConfig) - } - - companion object { - private var instance : PushProxWorkerCache? = null - - fun getInstance(getContext: () -> Context) : PushProxWorkerCache { - if(instance == null){ - synchronized(PushProxWorkerCache::class.java){ - if (instance == null){ - instance = PushProxWorkerCache(getContext) - } - } - } - return instance!! - } - } -} \ No newline at end of file diff --git a/config.yaml b/config_file_structure.yaml similarity index 70% rename from config.yaml rename to config_file_structure.yaml index 9617c30..f55fdbe 100644 --- a/config.yaml +++ b/config_file_structure.yaml @@ -3,18 +3,18 @@ # Settings specific to exporting metrics using a HTTP server prometheus_server: - enabled: false # default - port: 22322 # default + enabled: true # default + port: 10101 # default # Settings specific to pushing metrics to pushprox proxy # This is handy for traversing network topologies such as NAT pushprox: - enabled: true # default + enabled: false # default # fully qualified domain name - fqdn: "some-fqdn" # string, no default value provided + fqdn: # string, no default value provided - proxy_url: "url" # string, no default value provided + proxy_url: # string, no default value provided # Settings specific to backfilling metrics using prometheus remote write # @@ -23,8 +23,8 @@ pushprox: remote_write: # scrape interval in seconds - enabled: true # default - scrape_interval: 60 # default + enabled: false # default + scrape_interval: 30 # default # where to post metrics - remote_write_endpoint: "rem-wrirte" # string, no default value provided + remote_write_endpoint: # string, no default value provided