mirror of
https://github.com/mii443/prometheus-android-exporter.git
synced 2025-12-03 11:08:21 +00:00
update prom config function in view model
This commit is contained in:
@@ -47,6 +47,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation 'androidx.work:work-multiprocess:2.8.1'
|
||||||
def core_version = "1.10.1"
|
def core_version = "1.10.1"
|
||||||
|
|
||||||
// custom - prometheus client java library
|
// custom - prometheus client java library
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
@@ -119,21 +118,6 @@ private fun TabPage(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onCheckedChangeServer(
|
|
||||||
value : Boolean,
|
|
||||||
promViewModel: PromViewModel,
|
|
||||||
showDialog : MutableState<String>
|
|
||||||
){
|
|
||||||
if (value) {
|
|
||||||
val result : String? = promViewModel.turnServerOn()
|
|
||||||
if(result != null){
|
|
||||||
showDialog.value = result
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
promViewModel.turnServerOff()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun PrometheusServerPage(
|
private fun PrometheusServerPage(
|
||||||
promViewModel: PromViewModel,
|
promViewModel: PromViewModel,
|
||||||
@@ -149,12 +133,14 @@ private fun PrometheusServerPage(
|
|||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
Text(text = "Turn on Android Exporter on default port ${promViewModel.getDefaultPort()}")
|
Text(
|
||||||
|
text = "Turn on Android Exporter on port ${uiState.promConfig.prometheusServerPort}"
|
||||||
|
)
|
||||||
Switch(
|
Switch(
|
||||||
checked = uiState.serverTurnedOn,
|
checked = uiState.promConfig.prometheusServerEnabled,
|
||||||
onCheckedChange = {value : Boolean? ->
|
onCheckedChange = {value : Boolean? ->
|
||||||
if(value != null){
|
if(value != null){
|
||||||
onCheckedChangeServer(value, promViewModel, showDialogText)
|
promViewModel.updatePromConfig(UpdatePromConfig.prometheusServerEnabled, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -197,22 +183,11 @@ private fun PushProxPage(
|
|||||||
modifier = Modifier.padding(bottom = 30.dp)
|
modifier = Modifier.padding(bottom = 30.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
if(uiState.pushProxTurnedOn){
|
|
||||||
Text(
|
|
||||||
text = """
|
|
||||||
To edit PushProx proxy URL or FQDN, turn it off first.
|
|
||||||
""".trimIndent(),
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
modifier = Modifier.padding(bottom = 12.dp),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
TextField(
|
TextField(
|
||||||
value = uiState.fqdn,
|
value = uiState.promConfig.pushproxFqdn,
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
enabled = !uiState.pushProxTurnedOn,
|
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
promViewModel.updatePushProxFQDN(it)
|
promViewModel.updatePromConfig(UpdatePromConfig.pushproxFqdn, it)
|
||||||
},
|
},
|
||||||
label = {
|
label = {
|
||||||
Text(text = "Fully Qualified Domain Name")
|
Text(text = "Fully Qualified Domain Name")
|
||||||
@@ -221,11 +196,10 @@ private fun PushProxPage(
|
|||||||
)
|
)
|
||||||
|
|
||||||
TextField(
|
TextField(
|
||||||
value = uiState.pushProxURL,
|
value = uiState.promConfig.pushproxProxyUrl,
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
enabled = !uiState.pushProxTurnedOn,
|
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
promViewModel.updatePushProxURL(it)
|
promViewModel.updatePromConfig(UpdatePromConfig.pushproxProxyUrl, it)
|
||||||
},
|
},
|
||||||
label = {
|
label = {
|
||||||
Text(text = "PushProx proxy URL")
|
Text(text = "PushProx proxy URL")
|
||||||
|
|||||||
@@ -11,37 +11,41 @@ import androidx.work.NetworkType
|
|||||||
import androidx.work.OneTimeWorkRequestBuilder
|
import androidx.work.OneTimeWorkRequestBuilder
|
||||||
import androidx.work.OutOfQuotaPolicy
|
import androidx.work.OutOfQuotaPolicy
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import com.birdthedeveloper.prometheus.android.prometheus.android.exporter.worker.PushProxConfig
|
|
||||||
import com.birdthedeveloper.prometheus.android.prometheus.android.exporter.worker.PushProxWorker
|
import com.birdthedeveloper.prometheus.android.prometheus.android.exporter.worker.PushProxWorker
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import java.lang.Exception
|
||||||
|
|
||||||
enum class ConfigFileState {
|
enum class ConfigFileState {
|
||||||
LOADING,
|
LOADING,
|
||||||
ERROR, // file not found or was not parsed
|
ERROR, // file was not parsed succesfully
|
||||||
MISSING,
|
MISSING,
|
||||||
SUCCESS
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class UpdatePromConfig {
|
||||||
|
prometheusServerEnabled,
|
||||||
|
prometheusServerPort,
|
||||||
|
pushproxEnabled,
|
||||||
|
pushproxFqdn,
|
||||||
|
pushproxProxyUrl,
|
||||||
|
remoteWriteEnabled,
|
||||||
|
remoteWriteScrapeInterval,
|
||||||
|
remoteWriteEndpoint,
|
||||||
|
}
|
||||||
|
|
||||||
data class PromUiState(
|
data class PromUiState(
|
||||||
val tabIndex : Int = 0,
|
val tabIndex : Int = 0,
|
||||||
val serverTurnedOn : Boolean = false,
|
val promConfig: PromConfiguration = PromConfiguration(),
|
||||||
val pushProxTurnedOn : Boolean = false,
|
|
||||||
val serverPort : Int? = null, // if null, use default port
|
|
||||||
val fqdn : String = "test.example.com",
|
|
||||||
val pushProxURL : String = "143.42.59.63:8080",
|
|
||||||
val configFileState : ConfigFileState = ConfigFileState.LOADING,
|
val configFileState : ConfigFileState = ConfigFileState.LOADING,
|
||||||
)
|
)
|
||||||
|
|
||||||
private val TAG : String = "PROMVIEWMODEL"
|
private val TAG : String = "PROMVIEWMODEL"
|
||||||
|
|
||||||
class PromViewModel(): ViewModel() {
|
class PromViewModel(): ViewModel() {
|
||||||
// constants
|
|
||||||
private val DEFAULT_SERVER_PORT : Int = 10101 //TODO register with prometheus community
|
|
||||||
private val PROM_UNIQUE_WORK : String = "prom_unique_job"
|
private val PROM_UNIQUE_WORK : String = "prom_unique_job"
|
||||||
|
|
||||||
|
|
||||||
@@ -50,23 +54,44 @@ class PromViewModel(): ViewModel() {
|
|||||||
|
|
||||||
private lateinit var getContext: () -> Context
|
private lateinit var getContext: () -> Context
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
loadConfigurationFile()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadConfigurationFile(){
|
||||||
Log.v(TAG, "Checking for configuration file")
|
Log.v(TAG, "Checking for configuration file")
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
//TODO check for configuration file
|
|
||||||
delay(1000)
|
val fileExists = PromConfiguration.configFileExists(context = getContext())
|
||||||
|
if (fileExists) {
|
||||||
|
val tempPromConfiguration : PromConfiguration
|
||||||
|
try {
|
||||||
|
tempPromConfiguration = PromConfiguration.loadFromConfigFile()
|
||||||
|
|
||||||
|
_uiState.update { current ->
|
||||||
|
current.copy(
|
||||||
|
promConfig = tempPromConfiguration,
|
||||||
|
configFileState = ConfigFileState.SUCCESS,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}catch (e : Exception){
|
||||||
|
_uiState.update { current ->
|
||||||
|
current.copy(configFileState = ConfigFileState.ERROR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
_uiState.update { current ->
|
_uiState.update { current ->
|
||||||
current.copy(configFileState = ConfigFileState.MISSING)
|
current.copy(configFileState = ConfigFileState.MISSING)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDefaultPort() : Int {
|
|
||||||
return DEFAULT_SERVER_PORT
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initializeWithApplicationContext(getContext : () -> Context){
|
fun initializeWithApplicationContext(getContext : () -> Context){
|
||||||
this.getContext = getContext
|
this.getContext = getContext
|
||||||
|
loadConfigurationFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateTabIndex(index : Int){
|
fun updateTabIndex(index : Int){
|
||||||
@@ -77,59 +102,11 @@ class PromViewModel(): ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPromServerPort() : Int{
|
fun startWorker(){
|
||||||
return if(_uiState.value.serverPort != null){
|
|
||||||
_uiState.value.serverPort!!
|
|
||||||
}else{
|
|
||||||
DEFAULT_SERVER_PORT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if result is not null, it contains an error message
|
|
||||||
fun turnServerOn() : String?{
|
|
||||||
try{
|
|
||||||
//TODO rewrite asap
|
|
||||||
// prometheusServer.startInBackground(
|
|
||||||
// PrometheusServerConfig(
|
|
||||||
// getPromServerPort(),
|
|
||||||
// ::performScrape
|
|
||||||
// )
|
|
||||||
// )
|
|
||||||
}catch(e : Exception){
|
|
||||||
Log.v(TAG, e.toString())
|
|
||||||
return "Prometheus server failed!"
|
|
||||||
}
|
|
||||||
|
|
||||||
_uiState.update { current ->
|
|
||||||
current.copy(
|
|
||||||
serverTurnedOn = true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
fun turnServerOff(){
|
|
||||||
//TODO implement
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun validatePushProxSettings() : String? {
|
|
||||||
val fqdn = _uiState.value.fqdn.trim().trim('\n')
|
|
||||||
val url = _uiState.value.pushProxURL.trim().trim('\n')
|
|
||||||
|
|
||||||
if( fqdn.isEmpty() ) return "Fully Qualified Domain Name cannot be empty!"
|
|
||||||
if( url.isEmpty() ) return "PushProx URL cannot be empty!"
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun launchPushProxUsingWorkManager(){
|
|
||||||
val workManagerInstance = WorkManager.getInstance(getContext())
|
val workManagerInstance = WorkManager.getInstance(getContext())
|
||||||
|
|
||||||
// worker configuration
|
// worker configuration
|
||||||
val inputData : Data = PushProxConfig(
|
val inputData : Data = _uiState.value.promConfig.toWorkData()
|
||||||
pushProxFqdn = _uiState.value.fqdn,
|
|
||||||
pushProxUrl = _uiState.value.pushProxURL,
|
|
||||||
).toData()
|
|
||||||
|
|
||||||
// constraints
|
// constraints
|
||||||
val constraints = Constraints.Builder()
|
val constraints = Constraints.Builder()
|
||||||
@@ -151,47 +128,54 @@ class PromViewModel(): ViewModel() {
|
|||||||
).enqueue()
|
).enqueue()
|
||||||
}
|
}
|
||||||
|
|
||||||
// if result is not null, it contains an error message
|
fun stopWorker(){
|
||||||
fun turnPushProxOn() : String?{
|
//TODO implement this thingy
|
||||||
val error : String? = validatePushProxSettings()
|
|
||||||
if(error != null){ return error }
|
|
||||||
|
|
||||||
// idempotent call
|
|
||||||
launchPushProxUsingWorkManager()
|
|
||||||
|
|
||||||
_uiState.update { current ->
|
|
||||||
current.copy(
|
|
||||||
pushProxTurnedOn = true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun turnPushProxOff(){
|
|
||||||
val workerManagerInstance = WorkManager.getInstance(getContext())
|
val workerManagerInstance = WorkManager.getInstance(getContext())
|
||||||
workerManagerInstance.cancelUniqueWork(PROM_UNIQUE_WORK)
|
workerManagerInstance.cancelUniqueWork(PROM_UNIQUE_WORK)
|
||||||
|
|
||||||
_uiState.update {current ->
|
|
||||||
current.copy(
|
|
||||||
pushProxTurnedOn = false
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updatePushProxURL(url : String){
|
fun updatePromConfig(part : UpdatePromConfig, value : Any){
|
||||||
_uiState.update { current ->
|
when(part){
|
||||||
current.copy(
|
UpdatePromConfig.prometheusServerEnabled -> _uiState.update { current ->
|
||||||
pushProxURL = url
|
current.copy(promConfig = current.promConfig.copy(
|
||||||
)
|
prometheusServerEnabled = value as Boolean
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
UpdatePromConfig.prometheusServerPort -> _uiState.update { current ->
|
||||||
|
current.copy(promConfig = current.promConfig.copy(
|
||||||
|
prometheusServerPort = value as Int,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
UpdatePromConfig.pushproxEnabled -> _uiState.update { current ->
|
||||||
|
current.copy(promConfig = current.promConfig.copy(
|
||||||
|
pushproxEnabled = value as Boolean,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
UpdatePromConfig.pushproxFqdn -> _uiState.update { current ->
|
||||||
|
current.copy(promConfig = current.promConfig.copy(
|
||||||
|
pushproxFqdn = value as String,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
UpdatePromConfig.pushproxProxyUrl -> _uiState.update { current ->
|
||||||
|
current.copy(promConfig = current.promConfig.copy(
|
||||||
|
pushproxProxyUrl = value as String,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
UpdatePromConfig.remoteWriteEnabled -> _uiState.update { current ->
|
||||||
|
current.copy(promConfig = current.promConfig.copy(
|
||||||
|
remoteWriteEnabled = value as Boolean,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
UpdatePromConfig.remoteWriteScrapeInterval -> _uiState.update { current ->
|
||||||
|
current.copy(promConfig = current.promConfig.copy(
|
||||||
|
remoteWriteScrapeInterval = value as Int,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
UpdatePromConfig.remoteWriteEndpoint -> _uiState.update { current ->
|
||||||
|
current.copy(promConfig = current.promConfig.copy(
|
||||||
|
remoteWriteEndpoint = value as String,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updatePushProxFQDN(fqdn : String){
|
|
||||||
_uiState.update { current ->
|
|
||||||
current.copy(
|
|
||||||
fqdn = fqdn
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.birdthedeveloper.prometheus.android.prometheus.android.exporter.compose
|
package com.birdthedeveloper.prometheus.android.prometheus.android.exporter.compose
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import androidx.work.Data
|
import androidx.work.Data
|
||||||
import androidx.work.workDataOf
|
import androidx.work.workDataOf
|
||||||
|
|
||||||
@@ -11,16 +12,17 @@ data class PromConfiguration(
|
|||||||
val prometheusServerEnabled : Boolean = true,
|
val prometheusServerEnabled : Boolean = true,
|
||||||
val prometheusServerPort : Int = defaultPrometheusServerPort,
|
val prometheusServerPort : Int = defaultPrometheusServerPort,
|
||||||
val pushproxEnabled : Boolean = false,
|
val pushproxEnabled : Boolean = false,
|
||||||
val pushproxFqdn : String? = null,
|
val pushproxFqdn : String = "",
|
||||||
val pushproxProxyUrl : String? = null,
|
val pushproxProxyUrl : String = "",
|
||||||
val remoteWriteEnabled : Boolean = false,
|
val remoteWriteEnabled : Boolean = false,
|
||||||
val remoteWriteScrapeInterval : Int = defaultRemoteWriteScrapeInterval,
|
val remoteWriteScrapeInterval : Int = defaultRemoteWriteScrapeInterval,
|
||||||
val remoteWriteEndpoint : String? = null,
|
val remoteWriteEndpoint : String = "",
|
||||||
) {
|
) {
|
||||||
private val filepath : String = ""
|
private val filepath : String = "config.yaml"
|
||||||
|
private val alternativeFilepath : String = "config.yml"
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
suspend fun configFileExists(): Boolean {
|
suspend fun configFileExists(context : Context): Boolean {
|
||||||
//TODO implement this asap
|
//TODO implement this asap
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -30,11 +32,11 @@ data class PromConfiguration(
|
|||||||
prometheusServerEnabled = data.getBoolean("0", true),
|
prometheusServerEnabled = data.getBoolean("0", true),
|
||||||
prometheusServerPort = data.getInt("1", defaultPrometheusServerPort),
|
prometheusServerPort = data.getInt("1", defaultPrometheusServerPort),
|
||||||
pushproxEnabled = data.getBoolean("2", false),
|
pushproxEnabled = data.getBoolean("2", false),
|
||||||
pushproxFqdn = data.getString("3"),
|
pushproxFqdn = data.getString("3") ?: "",
|
||||||
pushproxProxyUrl = data.getString("4"),
|
pushproxProxyUrl = data.getString("4") ?: "",
|
||||||
remoteWriteEnabled = data.getBoolean("5", false),
|
remoteWriteEnabled = data.getBoolean("5", false),
|
||||||
remoteWriteScrapeInterval = data.getInt("6", defaultRemoteWriteScrapeInterval),
|
remoteWriteScrapeInterval = data.getInt("6", defaultRemoteWriteScrapeInterval),
|
||||||
remoteWriteEndpoint = data.getString("7"),
|
remoteWriteEndpoint = data.getString("7") ?: "",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.birdthedeveloper.prometheus.android.prometheus.android.exporter.worker
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.work.WorkerParameters
|
||||||
|
import androidx.work.multiprocess.RemoteCoroutineWorker
|
||||||
|
import com.birdthedeveloper.prometheus.android.prometheus.android.exporter.compose.PromConfiguration
|
||||||
|
|
||||||
|
private val TAG = "Worker"
|
||||||
|
|
||||||
|
class PromWorker(
|
||||||
|
val context : Context,
|
||||||
|
val parameters : WorkerParameters,
|
||||||
|
) : RemoteCoroutineWorker(context = context, parameters = parameters) {
|
||||||
|
|
||||||
|
override suspend fun doRemoteWork(): Result {
|
||||||
|
val inputConfiguration : PromConfiguration = PromConfiguration.fromWorkData(inputData)
|
||||||
|
|
||||||
|
while(true){
|
||||||
|
Log.v(TAG, "Worker is working")
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO implement this asap
|
||||||
|
|
||||||
|
return Result.success()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user