A language for expressing the condition for rate limiting.
An expression is of format LHS
OPERATOR
RHS
e.g jvm.thread.count.started > 99
LHS
= jvm.thread.count
, OPERATOR
= >
, RHS
= 99
format | example | description |
---|---|---|
LHS = RHS | jvm.thread.count < 22 | true, when the jvm.thread.count is less than 22 |
LHS[key] = val | sys.environment[limited] = true | true, when system environment named limited equals true |
LHS = [A ⎢ B] | jvm.current.thread.state = [BLOCKED ⎢ WAITING] | true, when the current thread state is either BLOCKED or WAITING |
LHS[key] = [A ⎢ B] | sys.environment[name] = [val_0 ⎢ val_1] | true, when either val_0 or val_1 is value of system environment name |
LHS[key] = [A & B] | sys.property[name] = [val_0 & val_1] | true, when both val_0 and val_1 are values of system property name |
class MatchExamples {
Matcher matchMemoryLessThan1g = Matchers.ofExpression("jvm.memory.available < 1GB");
Matcher matchMemoryLt9gAndTimeElapsedGt2s = Matchers.ofExpression("jvm.memory.available < 9GB & sys.time.elapsed > PT2S");
Matcher matchDeadlockedThreadsGt30 = Matchers.ofExpression("jvm.thread.count.deadlocked > 30");
Matcher matchSysUserNotGuest = Matchers.ofExpression("sys.property = {user.name != guest}");
}
class Resource {
// 5 permits per second when available system memory is less than 1 GB
RateLimiter rateLimiter = RateLimiter.of(Bandwidths.ofSeconds(5));
Matcher matchMemoryLessThanOneG = Matcher.of("jvm.memory.available < 1GB");
long startTime = System.currentTimeMillis();
String greet(String who) {
if (matchMemoryLessThanOneG.matches(startTime)) {
if (!rateLimiter.tryAcquire(1)) {
throw new RuntimeException("Rate limit exceeded");
}
}
return "Hello " + who;
}
}
name | description |
---|---|
jvm.thread.count |
|
jvm.thread.count.daemon |
|
jvm.thread.count.deadlocked |
|
jvm.thread.count.deadlocked.monitor |
|
jvm.thread.count.peak |
|
jvm.thread.count.started |
|
jvm.thread.current.count.blocked |
|
jvm.thread.current.count.waited |
jvm.thread(.current).count supported format digits
e.g 128
, 9
name | description |
---|---|
jvm.thread.current.id |
The id of the thread in digits e.g 128 , 9 |
name | description |
---|---|
jvm.thread.current.state |
java.lang.Thread.State of the current thread. |
jvm.thread.current.suspended |
if the current thread is suspended |
jvm.thread.current.state supported RHS values [NEW | RUNNABLE |BLOCKED | WAITING | TIMED_WAITING | TERMINATED]
jvm.thread.current.suspended supported RHS values [true | false]
name | description |
---|---|
jvm.thread.current.time.blocked |
|
jvm.thread.current.time.cpu |
|
jvm.thread.current.time.user |
|
jvm.thread.current.time.waited |
jvm.thread.current.time supported input formats: ISO-8601 duration format PnDTnHnMn.nS
with days
considered to be exactly 24 hours. See java.time.Duration#parse(CharSequence)
for some
examples of this format
name | description |
---|---|
sys.environment |
Use environment key-value pairs e.g sys.environment = { LANG = C} |
Support must be provided for the expression. Support is provided by default for the following:
name | description |
---|---|
jvm.memory.available |
(available memory in the JVM i.e. Maximum heap size (Xmx ) minus used memory) |
jvm.memory.free |
(amount of free memory in the JVM) |
jvm.memory.max |
(max amount of memory that the JVM will attempt to use) |
jvm.memory.total |
(total amount of memory in the JVM) |
jvm.memory.used |
(total minus free memory) |
jvm.memory supported input formats: digits
, digits[B|KB|MB|GB|TB|PB|EB|ZB|YB]
e.g 1000000
, 1_000_000
, 1GB
, 1gb
name | description |
---|---|
sys.property |
Use property key-value pairs e.g sys.property = {user.name != guest} |
name | description |
---|---|
sys.time |
(local date time) |
sys.time.elapsed |
(time elapsed since application start) |
sys.time supported input formats: ISO-8601 Time formats:
uuuu-MM-dd'T'HH:mm
uuuu-MM-dd'T'HH:mm:ss
uuuu-MM-dd'T'HH:mm:ss.SSS
uuuu-MM-dd'T'HH:mm:ss.SSSSSS
uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS
sys.time.elapsed supported input formats: ISO-8601 duration format PnDTnHnMn.nS
with days
considered to be exactly 24 hours. See java.time.Duration#parse(CharSequence)
for some
examples of this format.
=
EQUALS
>
GREATER
>=
GREATER_OR_EQUALS
<
LESS
<=
LESS_OR_EQUALS
%
LIKE
^
STARTS_WITH
$
ENDS_WITH
!
NOT (Negates other operators e.g !=
or !%
)