Quarkus Business Score
This extension offers a convenient way to detect application zombies, i.e. applications that live and communicate but do not produce any business value. The "business value" means anything that helps to solve a problem of an application user. Infrastructure stuff (logs, stats, metrics, health checks) usually does not produce a business value.
Key concepts
In a nutshell, this extension manages the business score which is a numeric representation of the business value.
An application emits score records to increase the business score, either directly with the BusinessScore
API or with an interceptor binding.
The records are only kept for the specific amount of time - time window.
The sum of all score records in the current time window is the current business score.
The zombie threshold defines the point at which the application is considered a zombie.
An external system or the application itself can periodically check the business score and react appropriately.
Core
If you want to use this extension, you need to add the io.quarkiverse.businessscore:quarkus-business-score
extension first.
For instance, with Maven, add the following dependency to your POM file:
<dependency>
<groupId>io.quarkiverse.businessscore</groupId>
<artifactId>quarkus-business-score</artifactId>
<version>1.0.0.Alpha4</version>
</dependency>
How to score
Quarkus provides a CDI bean of type io.quarkiverse.businessscore.BusinessScore
that can be used to increase and also to query the current score.
BusinessScore
exampleimport jakarta.enterprise.context.ApplicationScoped;
import io.quarkiverse.businessscore.BusinessScore;
@ApplicationScoped
public class MyService {
@Inject
BusinessScore bs; (1)
public void doSomeBusiness() {
bs.score(10); (2)
// ...
}
}
1 | Inject the business score of the current application. |
2 | Increase the business score by 10 . |
Alternatively, the @io.quarkiverse.businessscore.Scored
interceptor binding can be used to increase the score using an interceptor.
@Scored
exampleimport
import io.quarkiverse.businessscore.BusinessScore;
@ApplicationScoped
public class MyService {
@Scored(10) (1)
public void doSomeBusiness() {
// ...
}
}
1 | Increase the business score of the current application by 10 . |
How to check the business score
You can inject the io.quarkiverse.businessscore.BusinessScore
and check the "zombie" status with the BusinessScore#test()
method.
BusinessScore
exampleimport jakarta.enterprise.context.ApplicationScoped;
import io.quarkiverse.businessscore.BusinessScore;
@ApplicationScoped
public class MyService {
@Inject
BusinessScore bs; (1)
public void check() {
if (bs.test().isZombie()) {
// TODO warn the application admin!
}
}
}
1 | Inject the business score of the current application. |
HTTP module
This module integrates with the HTTP extension and registers two additional management endpoints:
-
/q/business-score
- shows the current score, zombie status, etc. -
/q/business-score/records
- shows all score records in the current time window
<dependency>
<groupId>io.quarkiverse.businessscore</groupId>
<artifactId>quarkus-business-score-http</artifactId>
<version>1.0.0.Alpha4</version>
</dependency>
/q/business-score
response example{
"serverTime": "2024-06-13T15:14:20.794528118",
"application": {
"name": "quarkus-business-score-integration-tests",
"version": "999-SNAPSHOT"
},
"zombie": false,
"score": 1,
"zombieThreshold": 20,
"initialZombieThreshold": 10,
"timeWindow": "PT72H",
"initialTimeWindow": "PT168H"
}
/q/business-score/records
response example{
"serverTime": "2024-06-13T15:14:21.259640872",
"application": {
"name": "quarkus-business-score-integration-tests",
"version": "999-SNAPSHOT"
},
"records": [
{
"value": 1,
"timestamp": "2024-06-13T13:14:20.735Z"
},
{
"value": 1,
"timestamp": "2024-07-13T13:14:20.135Z"
}
]
}
Self-check module
This module integrates with the Scheduler extension and registers an additional @Scheduled
method.
The current application is tested periodically and if a zombie is detected then a warning message is logged and a CDI event of type io.quarkiverse.businessscore.BusinessScore.ZombieStatus
is fired synchronously.
The CRON trigger used to schedule an automatic self-check can be configured with the quarkus.business-score.self-check.cron
configuration property.
<dependency>
<groupId>io.quarkiverse.businessscore</groupId>
<artifactId>quarkus-business-score-self-check</artifactId>
<version>1.0.0.Alpha4</version>
</dependency>
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
@ApplicationScoped
public class MyService {
void onZombie(@Observes BusinessScore.ZombieStatus status) { (1)
// TODO warn the application admin!
}
}
1 | Observe the ZombieStatus and react appropriately. |
If quarkus.business-score.self-check
is set to true
then the shutdown process is initiated when a zombie a zombie is detected.
Health module
This module integrates with the SmallRye Health extension and registers a @Wellness
health check automatically.
The name of the health check is business-score
.
It reports the status UP
if the app is NOT considered a zombie.
The health check is accessible through the /q/health/well
endpoint.
<dependency>
<groupId>io.quarkiverse.businessscore</groupId>
<artifactId>quarkus-business-score-health</artifactId>
<version>1.0.0.Alpha4</version>
</dependency>
/q/health/well
response example{
"status": "UP",
"checks": [
{
"name": "business-score",
"status": "UP",
"data": {
"score": 0,
"zombieThreshold": 10,
"timeWindow": "PT10H"
}
}
]
}
Mailer module
This module integrates with the Mailer extension and sends an email automatically when a self-test perfomed by the Self-check module fails, i.e. when a zombie is detected.
The from
, to
and subject
fields are configurable.
<dependency>
<groupId>io.quarkiverse.businessscore</groupId>
<artifactId>quarkus-business-score-mailer</artifactId>
<version>1.0.0.Alpha4</version>
</dependency>
Extension Configuration Reference
Configuration property fixed at build time - All other configuration properties are overridable at runtime
Configuration property |
Type |
Default |
---|---|---|
The point at which the application is considered a zombie. An application is considered a zombie if the current score is below the threshold in the current time window. Environment variable: |
long |
|
The amount of time a score record is kept alive. By default, it is kept for one week. Environment variable: |
|
|
The limit at which the extension will remove all records outside the current time window. Environment variable: |
int |
|
About the Duration format
To write duration values, use the standard You can also use a simplified format, starting with a number:
In other cases, the simplified format is translated to the
|
Configuration property fixed at build time - All other configuration properties are overridable at runtime
Configuration property |
Type |
Default |
---|---|---|
The root path for management endpoints. By default, this value is resolved as a path relative to Environment variable: |
string |
|
Configuration property fixed at build time - All other configuration properties are overridable at runtime
Configuration property |
Type |
Default |
---|---|---|
The CRON trigger used to schedule an automatic self-check. If Environment variable: |
string |
|
If set to Environment variable: |
boolean |
|
Configuration property fixed at build time - All other configuration properties are overridable at runtime
Configuration property |
Type |
Default |
---|---|---|
The sender address. Environment variable: |
string |
required |
The comma-separated list of recipients. Environment variable: |
string |
required |
The subject. The value is used as a Qute template with available data: Environment variable: |
string |
|