remove pushprox worker

This commit is contained in:
Martin Ptáček
2023-05-31 13:37:28 +02:00
parent 15fe164855
commit eb9744373a
7 changed files with 106 additions and 144 deletions

5
.gitignore vendored
View File

@ -1 +1,4 @@
credentials/
credentials/
# configuration for working version of Android prometheus exporter
config.yaml

View File

@ -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

View File

@ -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)
}
}
}
}

View File

@ -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()
}
}

View File

@ -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)
}
}

View File

@ -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!!
}
}
}

View File

@ -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