mirror of
https://github.com/mii443/prometheus-android-exporter.git
synced 2025-08-22 15:15:35 +00:00
remove pushprox worker
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@ -1 +1,4 @@
|
|||||||
credentials/
|
credentials/
|
||||||
|
|
||||||
|
# configuration for working version of Android prometheus exporter
|
||||||
|
config.yaml
|
||||||
|
11
README.md
11
README.md
@ -16,6 +16,17 @@ to run as ROOT. Exposes various hardware sensor metrics.
|
|||||||
|
|
||||||
# Client
|
# 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
|
||||||
ADB port forwarding is usefull when running the client application
|
ADB port forwarding is usefull when running the client application
|
||||||
on android emulator and prometheus database on the host
|
on android emulator and prometheus database on the host
|
||||||
|
@ -99,9 +99,15 @@ class PromViewModel(): ViewModel() {
|
|||||||
when(_uiState.value.exporterState) {
|
when(_uiState.value.exporterState) {
|
||||||
ExporterState.Running -> {
|
ExporterState.Running -> {
|
||||||
stopWorker()
|
stopWorker()
|
||||||
|
_uiState.update { current ->
|
||||||
|
current.copy(exporterState = ExporterState.NotRunning)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ExporterState.NotRunning -> {
|
ExporterState.NotRunning -> {
|
||||||
startWorker()
|
startWorker()
|
||||||
|
_uiState.update { current ->
|
||||||
|
current.copy(exporterState = ExporterState.Running)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,10 @@ import android.content.Context
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.work.Data
|
import androidx.work.Data
|
||||||
import androidx.work.workDataOf
|
import androidx.work.workDataOf
|
||||||
import com.birdthedeveloper.prometheus.android.prometheus.android.exporter.worker.PushProxConfig
|
|
||||||
import com.charleskorn.kaml.Yaml
|
import com.charleskorn.kaml.Yaml
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.decodeFromString
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.decodeFromString
|
|
||||||
|
|
||||||
private const val TAG : String = "CONFIGURATION"
|
private const val TAG : String = "CONFIGURATION"
|
||||||
|
|
||||||
@ -56,6 +53,7 @@ data class RemoteWriteConfigFile(
|
|||||||
val remote_write_endpoint : String?,
|
val remote_write_endpoint : String?,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// configuration of a work manager worker
|
||||||
@Serializable
|
@Serializable
|
||||||
data class PromConfiguration(
|
data class PromConfiguration(
|
||||||
// the following are default values for various configuration settings
|
// the following are default values for various configuration settings
|
||||||
@ -70,7 +68,6 @@ data class PromConfiguration(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
fun toStructuredText() : String {
|
fun toStructuredText() : String {
|
||||||
//TODO asap
|
|
||||||
return """
|
return """
|
||||||
prometheus_server:
|
prometheus_server:
|
||||||
enabled: $prometheusServerEnabled
|
enabled: $prometheusServerEnabled
|
||||||
@ -108,24 +105,22 @@ data class PromConfiguration(
|
|||||||
|
|
||||||
val file = File(context.filesDir, filename)
|
val file = File(context.filesDir, filename)
|
||||||
val alternativeFile = File(context.filesDir, alternativeFilename)
|
val alternativeFile = File(context.filesDir, alternativeFilename)
|
||||||
val fileContents : String
|
val fileContents : String = if (file.exists()){
|
||||||
if (file.exists()){
|
file.readText()
|
||||||
fileContents = file.readText()
|
|
||||||
}else if (alternativeFile.exists()){
|
}else if (alternativeFile.exists()){
|
||||||
fileContents = alternativeFile.readText()
|
alternativeFile.readText()
|
||||||
}else{
|
}else{
|
||||||
throw Exception("configuration file does not exist!")
|
throw Exception("configuration file does not exist!")
|
||||||
}
|
}
|
||||||
|
|
||||||
val parsedYaml : PromConfigFile = Yaml.default.decodeFromString(
|
val parsedConfig : PromConfigFile = Yaml.default.decodeFromString(
|
||||||
PromConfigFile.serializer(),
|
PromConfigFile.serializer(),
|
||||||
fileContents
|
fileContents
|
||||||
)
|
)
|
||||||
|
|
||||||
Log.v(TAG, parsedYaml.prometheus_server?.port.toString())
|
Log.v(TAG, parsedConfig.prometheus_server?.port.toString())
|
||||||
|
|
||||||
|
return parsedConfig.toPromConfiguration()
|
||||||
return parsedYaml.toPromConfiguration()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,37 +1,94 @@
|
|||||||
package com.birdthedeveloper.prometheus.android.prometheus.android.exporter.worker
|
package com.birdthedeveloper.prometheus.android.prometheus.android.exporter.worker
|
||||||
|
|
||||||
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.work.CoroutineWorker
|
import androidx.work.CoroutineWorker
|
||||||
|
import androidx.work.ForegroundInfo
|
||||||
|
import androidx.work.WorkManager
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
|
import com.birdthedeveloper.prometheus.android.prometheus.android.exporter.R
|
||||||
import com.birdthedeveloper.prometheus.android.prometheus.android.exporter.compose.PromConfiguration
|
import com.birdthedeveloper.prometheus.android.prometheus.android.exporter.compose.PromConfiguration
|
||||||
import io.ktor.client.HttpClient
|
import io.prometheus.client.CollectorRegistry
|
||||||
import io.ktor.client.engine.cio.CIO
|
import io.prometheus.client.exporter.common.TextFormat
|
||||||
import io.ktor.client.statement.HttpResponse
|
import java.io.StringWriter
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import java.time.LocalDateTime
|
|
||||||
import io.ktor.client.request.*
|
|
||||||
|
|
||||||
private val TAG = "Worker"
|
private const val TAG = "Worker"
|
||||||
|
|
||||||
class PromWorker(
|
class PromWorker(
|
||||||
context : Context,
|
context : Context,
|
||||||
parameters : WorkerParameters,
|
parameters : WorkerParameters,
|
||||||
) : CoroutineWorker(context, parameters) {
|
) : 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 {
|
override suspend fun doWork(): Result {
|
||||||
val inputConfiguration : PromConfiguration = PromConfiguration.fromWorkData(inputData)
|
val inputConfiguration : PromConfiguration = PromConfiguration.fromWorkData(inputData)
|
||||||
|
|
||||||
while(true){
|
// set foreground - //TODO is this right for the use case?
|
||||||
Log.v(TAG, "Worker is working " + LocalDateTime.now().toString())
|
setForeground(createForegroundInfo())
|
||||||
//TODO curl localhost
|
|
||||||
|
|
||||||
delay(1000L)
|
initializeWork(inputConfiguration)
|
||||||
}
|
startServices(inputConfiguration)
|
||||||
|
|
||||||
//TODO implement this asap
|
//TODO implement this asap
|
||||||
|
|
||||||
return Result.success()
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -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!!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,18 +3,18 @@
|
|||||||
# Settings specific to exporting metrics using a HTTP server
|
# Settings specific to exporting metrics using a HTTP server
|
||||||
prometheus_server:
|
prometheus_server:
|
||||||
|
|
||||||
enabled: false # default
|
enabled: true # default
|
||||||
port: 22322 # default
|
port: 10101 # default
|
||||||
|
|
||||||
# Settings specific to pushing metrics to pushprox proxy
|
# Settings specific to pushing metrics to pushprox proxy
|
||||||
# This is handy for traversing network topologies such as NAT
|
# This is handy for traversing network topologies such as NAT
|
||||||
pushprox:
|
pushprox:
|
||||||
|
|
||||||
enabled: true # default
|
enabled: false # default
|
||||||
# fully qualified domain name
|
# 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
|
# Settings specific to backfilling metrics using prometheus remote write
|
||||||
#
|
#
|
||||||
@ -23,8 +23,8 @@ pushprox:
|
|||||||
remote_write:
|
remote_write:
|
||||||
|
|
||||||
# scrape interval in seconds
|
# scrape interval in seconds
|
||||||
enabled: true # default
|
enabled: false # default
|
||||||
scrape_interval: 60 # default
|
scrape_interval: 30 # default
|
||||||
|
|
||||||
# where to post metrics
|
# where to post metrics
|
||||||
remote_write_endpoint: "rem-wrirte" # string, no default value provided
|
remote_write_endpoint: # string, no default value provided
|
Reference in New Issue
Block a user