mirror of
https://github.com/mii443/prometheus-android-exporter.git
synced 2025-08-22 15:15:35 +00:00
compiles
This commit is contained in:
@ -8,13 +8,25 @@ import androidx.room.PrimaryKey
|
|||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import androidx.room.Room
|
import androidx.room.Room
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import remote.write.RemoteWrite.TimeSeries
|
||||||
|
|
||||||
//TODO
|
/// Room is a relational database
|
||||||
|
/// Contains the following tables:
|
||||||
|
/// - Timeseries table:
|
||||||
|
/// + labels : List<TimeSeriesLabel> sorted alphabetically and encoded in json
|
||||||
|
/// - Sample table:
|
||||||
|
/// + id
|
||||||
|
/// + timestamp
|
||||||
|
/// + value
|
||||||
|
/// + Timeseries foreign key
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
data class RoomTimeSeries {
|
data class RoomTimeSeries (
|
||||||
|
@PrimaryKey(autoGenerate = false)
|
||||||
}
|
val labels : String
|
||||||
|
)
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
data class RoomSample(
|
data class RoomSample(
|
||||||
@ -24,12 +36,16 @@ data class RoomSample(
|
|||||||
val value : Double,
|
val value : Double,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TimeSeriesLabelList(
|
||||||
|
val labels: List<TimeSeriesLabel>
|
||||||
|
)
|
||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
entities = [RoomTimeSeries::class, RoomSample::class],
|
entities = [RoomTimeSeries::class, RoomSample::class],
|
||||||
version = 1
|
version = 1
|
||||||
)
|
)
|
||||||
abstract class RemoteWriteDatabase: RoomDatabase() {
|
abstract class RemoteWriteDatabase: RoomDatabase() {
|
||||||
|
|
||||||
abstract val dao: RoomDao
|
abstract val dao: RoomDao
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +57,7 @@ interface RoomDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Query("") //TODO
|
@Query("") //TODO
|
||||||
fun getNumberOfTimeSeriesSamples(){
|
fun getNumberOfTimeSeriesSamples(number : Int){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,31 +69,27 @@ interface RoomDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class RemoteWriteSenderDbStorage(getContext: () -> Context) : RemoteWriteSenderStorage(){
|
class RemoteWriteSenderDbStorage(getContext: () -> Context) : RemoteWriteSenderStorage(){
|
||||||
|
companion object{
|
||||||
|
const val dbName = "prometheus.db"
|
||||||
|
}
|
||||||
|
|
||||||
private val roomDb by lazy {
|
private val roomDb by lazy {
|
||||||
Room.databaseBuilder(
|
Room.databaseBuilder(
|
||||||
getContext(),
|
getContext(),
|
||||||
RemoteWriteDatabase::class.java,
|
RemoteWriteDatabase::class.java,
|
||||||
"contacts.db"
|
dbName,
|
||||||
).build()
|
).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun encodeLabels(labelsList: List<TimeSeriesLabel>) : String{
|
private fun encodeLabels(labelsList: List<TimeSeriesLabel>) : String{
|
||||||
//TODO
|
/// preserve the same order
|
||||||
var result : String = ""
|
val sorted : List<TimeSeriesLabel> = labelsList.sortedBy { it.name }
|
||||||
for (label in labelsList){
|
val timeSeriesLabelList = TimeSeriesLabelList(labels = sorted)
|
||||||
// check if label contains escape character
|
return Json.encodeToString(TimeSeriesLabelList.serializer(), timeSeriesLabelList)
|
||||||
if (label.name.contains("-") || label.value.contains("-")){
|
|
||||||
throw IllegalArgumentException("Time series labels should not contain \'-\'")
|
|
||||||
}else{
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun decodeLabels(labels : String) : List<TimeSeriesLabel> {
|
private fun decodeLabels(labels : String) : List<TimeSeriesLabel> {
|
||||||
//TODO
|
return Json.decodeFromString<TimeSeriesLabelList>(labels).labels
|
||||||
}
|
}
|
||||||
override fun writeScrapedSample(metricsScrape: MetricsScrape) {
|
override fun writeScrapedSample(metricsScrape: MetricsScrape) {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
@ -98,5 +110,4 @@ class RemoteWriteSenderDbStorage(getContext: () -> Context) : RemoteWriteSenderS
|
|||||||
override fun getLength(): Int {
|
override fun getLength(): Int {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -8,11 +8,17 @@ import java.util.Queue
|
|||||||
// HashMap<List of labels including name, List of TimeSeries samples to this TimeSeries>
|
// HashMap<List of labels including name, List of TimeSeries samples to this TimeSeries>
|
||||||
private typealias ConverterHashMap = HashMap<List<TimeSeriesLabel>, MutableList<TimeSeriesSample>>
|
private typealias ConverterHashMap = HashMap<List<TimeSeriesLabel>, MutableList<TimeSeriesSample>>
|
||||||
|
|
||||||
class RemoteWriteSenderMemStorage : RemoteWriteSenderStorage() {
|
private const val TAG : String = "REMOTE_WRITE_SENDER_MEMORY_SIMPLE_STORAGE";
|
||||||
|
|
||||||
|
|
||||||
|
//TODO sort this out
|
||||||
|
|
||||||
|
class RemoteWriteSenderSimpleMemoryStorage : RemoteWriteSenderStorage() {
|
||||||
|
private val data: Queue<MetricsScrape> = LinkedList()
|
||||||
|
|
||||||
private fun filterExpiredMetrics(metrics : MutableList<MetricsScrape>){
|
private fun filterExpiredMetrics(metrics : MutableList<MetricsScrape>){
|
||||||
val now : Long = System.currentTimeMillis()
|
val now : Long = System.currentTimeMillis()
|
||||||
val oldestMetricTimeMs : Long = now() - maxMetricsAge * 1000
|
val oldestMetricTimeMs : Long = now - maxMetricsAge * 1000
|
||||||
var howManyMetricsRemove : Int = 0
|
var howManyMetricsRemove : Int = 0
|
||||||
|
|
||||||
// count how many metrics to remove
|
// count how many metrics to remove
|
||||||
@ -33,10 +39,9 @@ class RemoteWriteSenderMemStorage : RemoteWriteSenderStorage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun hashMapEntryToProtobufTimeSeries(
|
private fun hashMapEntryToProtobufTimeSeries(
|
||||||
labels: List<TimeSeriesLabel>, samples: MutableList<TimeSeriesSample>
|
labels: List<TimeSeriesLabel>, samples: MutableList<TimeSeriesSample>
|
||||||
): TimeSeries {
|
): RemoteWrite.TimeSeries {
|
||||||
|
|
||||||
val timeSeriesBuilder: RemoteWrite.TimeSeries.Builder = RemoteWrite.TimeSeries.newBuilder()
|
val timeSeriesBuilder: RemoteWrite.TimeSeries.Builder = RemoteWrite.TimeSeries.newBuilder()
|
||||||
|
|
||||||
@ -51,8 +56,8 @@ class RemoteWriteSenderMemStorage : RemoteWriteSenderStorage() {
|
|||||||
return timeSeriesBuilder.build()
|
return timeSeriesBuilder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hashmapToProtobufWriteRequest(hashMap: ConverterHashMap): WriteRequest {
|
private fun hashmapToProtobufWriteRequest(hashMap: ConverterHashMap): RemoteWrite.WriteRequest {
|
||||||
val writeRequestBuilder: WriteRequest.Builder = WriteRequest.newBuilder()
|
val writeRequestBuilder: RemoteWrite.WriteRequest.Builder = RemoteWrite.WriteRequest.newBuilder()
|
||||||
|
|
||||||
for (entry in hashMap) {
|
for (entry in hashMap) {
|
||||||
val timeSeries = hashMapEntryToProtobufTimeSeries(entry.key, entry.value)
|
val timeSeries = hashMapEntryToProtobufTimeSeries(entry.key, entry.value)
|
||||||
@ -62,6 +67,47 @@ class RemoteWriteSenderMemStorage : RemoteWriteSenderStorage() {
|
|||||||
return writeRequestBuilder.build()
|
return writeRequestBuilder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getScrapedSamplesCompressedProtobuf(howMany: Int): ByteArray {
|
||||||
|
if (howMany < 1) {
|
||||||
|
throw IllegalArgumentException("howMany must be bigger than zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
val scrapedMetrics: MutableList<MetricsScrape> = mutableListOf()
|
||||||
|
for (i in 1..howMany) {
|
||||||
|
val oneMetric: MetricsScrape? = data.poll()
|
||||||
|
if (oneMetric == null) {
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
scrapedMetrics.add(oneMetric)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.d(TAG, "Getting scraped samples: ${scrapedMetrics.size} samples")
|
||||||
|
|
||||||
|
filterExpiredMetrics(scrapedMetrics)
|
||||||
|
|
||||||
|
val writeRequest: RemoteWrite.WriteRequest = metricsScrapeListToProtobuf(scrapedMetrics.toList())
|
||||||
|
val bytes: ByteArray = writeRequest.toByteArray()
|
||||||
|
return RemoteWriteSenderStorage.encodeWithSnappy(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun metricsScrapeListToProtobuf(input: List<MetricsScrape>): RemoteWrite.WriteRequest {
|
||||||
|
if (input.isEmpty()) {
|
||||||
|
throw Exception("Input is empty!")
|
||||||
|
}
|
||||||
|
|
||||||
|
val hashmap: ConverterHashMap = HashMap()
|
||||||
|
|
||||||
|
for (metricsScrape in input) {
|
||||||
|
for (timeSeries in metricsScrape.timeSeriesList){
|
||||||
|
processStorageTimeSeries(hashmap, timeSeries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val result: RemoteWrite.WriteRequest = hashmapToProtobufWriteRequest(hashmap)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
private fun processStorageTimeSeries(hashMap: ConverterHashMap, timeSeries: StorageTimeSeries){
|
private fun processStorageTimeSeries(hashMap: ConverterHashMap, timeSeries: StorageTimeSeries){
|
||||||
|
|
||||||
// add remote write label to labels
|
// add remote write label to labels
|
||||||
@ -80,107 +126,6 @@ class RemoteWriteSenderMemStorage : RemoteWriteSenderStorage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun metricsScrapeListToProtobuf(input: List<MetricsScrape>): WriteRequest {
|
|
||||||
if (input.isEmpty()) {
|
|
||||||
throw Exception("Input is empty!")
|
|
||||||
}
|
|
||||||
|
|
||||||
val hashmap: ConverterHashMap = HashMap()
|
|
||||||
|
|
||||||
for (metricsScrape in input) {
|
|
||||||
for (timeSeries in metricsScrape.timeSeriesList){
|
|
||||||
processStorageTimeSeries(hashmap, timeSeries)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val result: WriteRequest = hashmapToProtobufWriteRequest(hashmap)
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private val data: Queue<MetricsScrape> = LinkedList()
|
|
||||||
|
|
||||||
override fun getScrapedSamplesCompressedProtobuf(howMany: Int): ByteArray {
|
|
||||||
if (howMany < 1) {
|
|
||||||
throw IllegalArgumentException("howMany must be bigger than zero")
|
|
||||||
}
|
|
||||||
|
|
||||||
val scrapedMetrics: MutableList<MetricsScrape> = mutableListOf()
|
|
||||||
for (i in 1..howMany) {
|
|
||||||
val oneMetric: MetricsScrape? = data.poll()
|
|
||||||
if (oneMetric == null) {
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
scrapedMetrics.add(oneMetric)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log.d(TAG, "Getting scraped samples: ${scrapedMetrics.size} samples")
|
|
||||||
|
|
||||||
filterExpiredMetrics(scrapedMetrics)
|
|
||||||
|
|
||||||
val writeRequest: WriteRequest = this.metricsScrapeListToProtobuf(scrapedMetrics.toList())
|
|
||||||
val bytes: ByteArray = writeRequest.toByteArray()
|
|
||||||
return this.encodeWithSnappy(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun removeNumberOfScrapedSamples(number: Int) {
|
|
||||||
if (number > 0) {
|
|
||||||
for (i in 1..number) {
|
|
||||||
if(data.isEmpty()){
|
|
||||||
break;
|
|
||||||
}else{
|
|
||||||
data.remove()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw IllegalArgumentException("number must by higher than 0")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun writeScrapedSample(metricsScrape: MetricsScrape) {
|
|
||||||
Log.d(TAG, "Writing scraped sample to storage")
|
|
||||||
data.add(metricsScrape)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isEmpty(): Boolean {
|
|
||||||
return data.isEmpty()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getLength(): Int {
|
|
||||||
return data.count()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//TODO sort this out
|
|
||||||
|
|
||||||
class RemoteWriteSenderSimpleMemoryStorage : RemoteWriteSenderStorage() {
|
|
||||||
private val data: Queue<MetricsScrape> = LinkedList()
|
|
||||||
|
|
||||||
override fun getScrapedSamplesCompressedProtobuf(howMany: Int): ByteArray {
|
|
||||||
if (howMany < 1) {
|
|
||||||
throw IllegalArgumentException("howMany must be bigger than zero")
|
|
||||||
}
|
|
||||||
|
|
||||||
val scrapedMetrics: MutableList<MetricsScrape> = mutableListOf()
|
|
||||||
for (i in 1..howMany) {
|
|
||||||
val oneMetric: MetricsScrape? = data.poll()
|
|
||||||
if (oneMetric == null) {
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
scrapedMetrics.add(oneMetric)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log.d(TAG, "Getting scraped samples: ${scrapedMetrics.size} samples")
|
|
||||||
|
|
||||||
filterExpiredMetrics(scrapedMetrics)
|
|
||||||
|
|
||||||
val writeRequest: RemoteWrite.WriteRequest = this.metricsScrapeListToProtobuf(scrapedMetrics.toList())
|
|
||||||
val bytes: ByteArray = writeRequest.toByteArray()
|
|
||||||
return this.encodeWithSnappy(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO use this thing
|
//TODO use this thing
|
||||||
override fun removeNumberOfScrapedSamples(number: Int) {
|
override fun removeNumberOfScrapedSamples(number: Int) {
|
||||||
if (number > 0) {
|
if (number > 0) {
|
||||||
|
@ -2,6 +2,7 @@ package com.birdthedeveloper.prometheus.android.prometheus.android.exporter.work
|
|||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import io.prometheus.client.Collector.MetricFamilySamples
|
import io.prometheus.client.Collector.MetricFamilySamples
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
import org.iq80.snappy.Snappy
|
import org.iq80.snappy.Snappy
|
||||||
import remote.write.RemoteWrite.Label
|
import remote.write.RemoteWrite.Label
|
||||||
import remote.write.RemoteWrite.Sample
|
import remote.write.RemoteWrite.Sample
|
||||||
@ -78,6 +79,7 @@ data class StorageTimeSeries(
|
|||||||
val labels : List<TimeSeriesLabel>,
|
val labels : List<TimeSeriesLabel>,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class TimeSeriesLabel(
|
data class TimeSeriesLabel(
|
||||||
val name: String,
|
val name: String,
|
||||||
val value: String,
|
val value: String,
|
||||||
|
Reference in New Issue
Block a user