Skip to content

Instantly share code, notes, and snippets.

@miere
Created May 4, 2019 00:28
Show Gist options
  • Save miere/dd737a1b04904ab03d0603576f44ccc6 to your computer and use it in GitHub Desktop.
Save miere/dd737a1b04904ab03d0603576f44ccc6 to your computer and use it in GitHub Desktop.
Lightweight Metrics for Java/Kotlin
import java.lang.management.ManagementFactory
import java.util.concurrent.atomic.AtomicLong
class MetricService {
val megaByte = 1024.0 * 1024.0
private val metrics = mutableMapOf<String, Metric>().apply {
val memory = ManagementFactory.getMemoryMXBean()
put("jvm.heap.used", Gauge(isLocal = true) { memory.heapMemoryUsage.used / megaByte })
put("jvm.heap.total", Gauge(isLocal = true) { memory.heapMemoryUsage.max / megaByte })
put("jvm.non-heap.used", Gauge(isLocal = true) { memory.nonHeapMemoryUsage.used / megaByte })
val threads = ManagementFactory.getThreadMXBean()
put("jvm.threads.total", Gauge(isLocal = true) { threads.threadCount.toDouble() })
}
/**
* Register a custom metric.
*/
fun register( metricName: String, metric: Metric ) {
metrics[metricName] = metric
}
/**
* Creates and memorize a new [Counter].
*/
fun newCounter( metricName: String, isLocal: Boolean = true ): Counter {
val counter = Counter(isLocal)
metrics[metricName] = counter.asMetric()
return counter
}
/**
* Returns all gathered metric values since last
* invocation of this method.
*/
fun metricsSnapshot(): Map<String, Metric> = metrics
}
/**
* Immutable representation of a metric.
*/
interface Metric {
fun get(): Double
fun isLocal(): Boolean
}
/**
* A gauge metric is an instantaneous reading of a particular value.
*/
class Gauge( isLocal: Boolean = false, internal val supplier: () -> Double ): Metric {
override fun get() = supplier.invoke()
override fun isLocal(): Boolean = isLocal()
}
/**
* A metric entry that holds a number that can be incremented.
* It will reset the counter whenever you get its value.
*/
class Counter( val isLocal: Boolean ) {
internal val counter = AtomicLong()
fun asMetric(): Metric = CounterMetric()
fun markOccurrence() {
incrementBy(1L)
}
fun incrementBy( amount: Long ) {
counter.addAndGet( amount )
}
inner class CounterMetric: Metric {
override fun get() = counter.getAndSet(0).toDouble()
override fun isLocal() = isLocal
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment