https://github.com/wsargent/blindsight-scripting
https://github.com/wsargent/blindsight-scripting
dynamic-logging jsr223 logging slf4j
Last synced: 8 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/wsargent/blindsight-scripting
- Owner: wsargent
- Created: 2021-05-02T06:06:52.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2021-05-08T01:18:24.000Z (over 4 years ago)
- Last Synced: 2025-01-09T18:03:59.971Z (9 months ago)
- Topics: dynamic-logging, jsr223, logging, slf4j
- Language: Scala
- Homepage: https://tersesystems.com/blog/2021/05/02/dynamic-logging-with-conditions/
- Size: 30.3 KB
- Stars: 0
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Dynamic Conditions with Scripting (Groovy / Tweakflow)
This project demonstrates how to change logging conditions in a running JVM, using Blindsight.
A condition has to return `Boolean` but is intentionally left open so that anything can be a condition. This means that we can tie a condition to a
[JSR 223 script](https://docs.oracle.com/en/java/javase/12/scripting/java-scripting-api.html#GUID-C4A6EB7C-0AEA-45EC-8662-099BDEFC361A).In this example, we'll use [Groovy](http://docs.groovy-lang.org/docs/latest/html/documentation/#jsr223) to evaluate a condition and return a boolean. If the groovy script changes, then the JVM picks it up and evaluates it without having to restart the JVM.
The groovy script can execute arbitrary logic in the JVM, so it's powerful but may be a security risk. A [Tweakflow](https://twineworks.github.io/tweakflow/index.html) condition manager is also included, which runs a tightly controlled script that only allows computation on explicit inputs. The TweakFlow script additionally has an HMAC signature that ensures that scripts have not been tampered with.
## Main
The main program runs a loop that conditionally logs various statements:
```scala
object Main {val logger: Logger = LoggerFactory.getLogger(getClass)
val cm = new ScriptConditionManager(Paths.get("src/main/groovy/condition.groovy"), "groovy")
//val cm = new TweakFlowConditionManager(Paths.get("src/main/tweakflow/condition.tf"))def main(args: Array[String]): Unit = {
// Run from a loop
while (true) {
logInfo()
logDebug()
logInfoSpecial()
logDebugSpecial()Thread.sleep(1000L)
}
}def logInfo(): Unit = {
logger.info.when(cm.condition()) { info =>
info("Logging at a info level")
}
}def logInfoSpecial(): Unit = {
logger.info.when(cm.condition()) { info =>
info("Logging at a info level from special method")
}
}def logDebugSpecial(): Unit = {
logger.debug.when(cm.condition()) { info =>
info("Logging at a debug level from special method")
}
}def logDebug(): Unit = {
logger.debug.when(cm.condition()) { handle =>
handle("Logging at a debug level")
}
}}
```## Groovy Script
There's a single Groovy script, `condition.groovy`. It runs a single method, which returns a boolean indicating whether logging should happen or not.
```groovy
import com.tersesystems.blindsight.Markers
import org.slf4j.event.Level
import sourcecode.Enclosing
import sourcecode.Fileboolean evaluate(Level level, Markers markers, Enclosing enclosing, File file) {
// We like this debug message so we want it to show up
var enc = enclosing.value()
if (enc == "com.tersesystems.blindsight.scripting.Main.logDebugSpecial") {
return true;
}// We don't like this info message
if (enc == "com.tersesystems.blindsight.scripting.Main.logInfoSpecial") {
return false;
}// Otherwise we'll just use info level.
return (level.toInt() >= Level.INFO.toInt())
}
```The `ConditionManager` and the `FileConditionSource` keep track of the file's last modification time. If the file's been modified since last scene, then the script is evaluated again, and the new script is used.
The `FileConditionSource` is a trivial example for the purposes of demonstration, and a JDBC `ConditionSource` or Redis `ConditionSource` could also be used to pull updated script information.
## Running
```
sbt run
```And then edit `condition.groovy` to your preference.
Hit Control-C to cancel the app.