可觀測性 - Observability 是雲原生應用又一重要因子。Kubernetes 是分散式的,會起多個 Pod 與許多 service 互動。在平台中會引入Cacti, Zabbix, Prometheus 這樣的監控系統來觀測應用,而應用需要提供收集的指標。一個好的監控應該包括系統基本的CPU, Memory 表現以及更重要的有商業義意的 Service Indicator 可以在後續知道系統的可靠度與價值。
Quarkus 提供了 Metrics 擴展,直接內建了 JVM 相關的統計指標。
Ouarkus 有提供容易客製的方式,讓我們提供客制化的指標,建立有商業價值的指標。那我們就可以從 SLI -> SLO -> SLA
Micrometer 定義了核心的指標型別,包涵計數 (Counter)、儀表板 (Gauges)、計時器 (Timer)等等,再配合以注冊的方式來達到客製化指標。並且可以介接不同的監控系統。Micrometer 使用 naming conventions 以轉換到不同的後端監控系統。Micrometer 用 dots "." 來分別區段,而在面對 Prometheus 時,會幫忙轉成 _
增加 pom.xml 的 dependency
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-micrometer</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.microprofile.metrics</groupId>
<artifactId>microprofile-metrics-api</artifactId>
</dependency>
這時加完, 執行 quarkus:dev 會有基本的 metrics
curl http://localhost:8080/q/metrics
加入 PrimeNumberChecker.kt
import org.eclipse.microprofile.metrics.MetricUnits
import org.eclipse.microprofile.metrics.annotation.Counted
import org.eclipse.microprofile.metrics.annotation.Gauge
import org.eclipse.microprofile.metrics.annotation.Timed
import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.Produces
import javax.ws.rs.core.MediaType
import kotlin.math.floor
import kotlin.math.sqrt
@Path("/prime")
class PrimeNumberChecker {
private var highestPrimeNumberSoFar: Long = 2
@GET
@Path("/{number}")
@Produces(MediaType.TEXT_PLAIN)
@Counted(name = "performedChecks", description = "How many primality checks have been performed.")
@Timed(name = "checksTimer", description = "timer", unit = MetricUnits.MILLISECONDS)
fun checkIfPrime(number: Long): String {
return when {
number < 1 -> "Only natural numbers can be prime numbers."
number == 1L -> "1 is not prime."
number == 2L -> "2 is prime."
number % 2 == 0L -> "$number is not prime, it is divisible by 2."
else -> {
var i = 3
while (i < floor(sqrt(number.toDouble())) + 1) {
if (number % i == 0L) {
return "$number is not prime, is divisible by $i."
}
i += 2
}
if (number > highestPrimeNumberSoFar) {
highestPrimeNumberSoFar = number
}
return "$number is prime."
}
}
}
@Gauge(name = "highestPrimeNumberSoFar", unit = MetricUnits.NONE, description = "Highest prime number so far.")
fun highestPrimeNumberSoFar(): Long {
return highestPrimeNumberSoFar
}
}
curl http://localhost:8080/prime/5
curl http://localhost:8080/prime/350
curl http://localhost:8080/prime/359
curl http://localhost:8080/prime/350
curl http://localhost:8080/prime/1187
可以看到 200 成功了 5次
也有我們客製化加入的指標