reactive-audit-agent

JVM Agent to detect blocking IO call

License

License

Categories

Categories

React User Interface Web Frameworks
GroupId

GroupId

com.octo.reactive.audit
ArtifactId

ArtifactId

reactive-audit-agent
Last Version

Last Version

0.8
Release Date

Release Date

Type

Type

zip
Description

Description

reactive-audit-agent
JVM Agent to detect blocking IO call
Project URL

Project URL

https://github.com/octo-online/reactive-audit
Source Code Management

Source Code Management

https://github.com/octo-online/reactive-audit

Download reactive-audit-agent

Dependencies

compile (2)

Group / Artifact Type Version
com.octo.reactive.audit : reactive-audit-lib jar 0.8
org.aspectj : aspectjrt jar 1.8.2

test (2)

Group / Artifact Type Version
junit : junit jar 4.11
org.aspectj : aspectjweaver jar 1.8.2

Project Modules

There are no modules declared in this project.

Introduction

This audit tool aims to provide help to the use of Reactive architecture in project implementations. For reminder, when applying this approach the application must use only non-blocking APIs and, as soon as possible, return the current thread to a pool, limited by the number of CPU cores. The code must also use Java 8 concurrency utility classes CompletableFuture<> everywhere. The frameworks Play, AKKA, Scala, RxJava or Vert.x promote this approach.

WARNING: This is a beta version

Now, 603 blocking methods are detected.

How it works

To detect where the application uses a blocking API, this tool injects some checks using a JVM agent (using Aspectj). We chose to use the load-time-weawing in order to not modify the compiled code. Thus, it is easier to add or remove the audit.

The agent tries to detect all the invocations of blocking APIs at runtime. It is not possible to detect them at compile time, because it depends on the specific running instance. For example, the Writer.write(..) can be used for a byte array in memory or for a socket.

Some threads can invoke a blocking API, others cannot. It is possible to select for which thread the agent must detect a call to a blocking API (parameter reactiveAudit_threadPattern).

At the application startup, it is common to use some blocking APIs to load parameters from a file, etc. Therefore, it is possible to shift the audit start time to a few seconds after the application startup (parameter reactiveAudit_bootstrapDelay). Or, it is possible to wait a pause in the process to detect the end of the application startup (parameter reactiveAudit_bootstrapMode=CPU).

Some blocking APIs are used to manage files. If the file system uses a SSD, the latency is low. But if the file system is on a NAS or on the Cloud, the latency is high. Therefore, it is possible to select the acceptable level of latency for all the file API. By default, only the medium and high latency file APIs generate an alert.

More info here

Download

Unzip this file and add the <audit home>/bin directory in PATH.

Usage

To set the environment variables, after add <audit home>/bin in PATH, use reactive-audit. This will set the variable REACTIVE_AUDIT_HOME to the reactive audit tool home directory and AUDIT_OPTS with the parameters needed to start a JVM. It's a shell script. Because this script must update some environment variable, with Mac/Linux you must invoke with source reactive-audit ....

You can add a framework or server name as a parameter of this command, such as catalina, jetty, play, etc. in order to apply a pre-defined configuration.

$ # Mac/Linux
$ source reactive-audit catalina
$ catalina run
> REM Windows
> reactive-audit catalina
> catalina run

The parameter -d is for debug. The parameter -s is for silent.

Else, you can use -run parameter to chain with the startup of the server.

$ # Mac/Linux
$ reactive-audit catalina -run catalina run
> REM Windows
> reactive-audit catalina -run catalina run

Note: The application startup can be SLOW. Each class to load must be inspected to detect and inject each audits rules.

Framework Windows Mac/linux
unknown > reactive-audit
> java %AUDIT_OPTS% ...
$ source reactive-audit
$ java %AUDIT_OPTS% ...
jetty > reactive-audit jetty
> java %AUDIT_OPTS% -jar start.jar
$ source reactive-audit jetty
$ java %AUDIT_OPTS% -jar start.jar
catalina > reactive-audit catalina -run catalina run $ reactive-audit catalina -run catalina run
play > reactive-audit play -run activator run $ reactive-audit play -run activator run
akka > reactive-audit akka -run activator run $ reactive-audit akka -run activator run
vert.x > reactive-audit vertx -run vertx run ... $ reactive-audit vertx -run vertx run ...
maven > reactive-audit maven -run mvn ... $ reactive-audit maven -run mvn ...
gradle > reactive-audit gradle -run gradle ... $ reactive-audit gradle -run gradle ...
sbt > reactive-audit sbt -run sbt ... $ reactive-audit sbt -run sbt ...

For the background, this script append the java.ext.dir with <audit home>/lib and adds the agent using -javaagent:<audit home>/lib/aspectjweaver.jar.

If a framework is selected, this script adds the pre-defined associated parameter file with -DreactiveAudit=<audit home>/etc/<framework>.properties. Sometimes other specific environment variables are set to start the framework.

Using a build tool

Reactive-audit can be used with build tools that support Maven repositories. See some samples with Maven, Gradle and SBT in the integration project

Annotations

With the reactive-audit-lib.jar, three annotations can be used.

@TolerateLatency force the JVM agent to tolerate a method call to a blocking API without log or exception. All blocking call from this method or from one of its callees is accepted without generating an alert.

@WithLatency declare that a specific method has latency. A call of this method can generate a log or throw a ReactiveAuditException if the audit agent is used.

@StartAudit start the audit when this method is executed, if reactiveAudit_bootstrapMode=ANNOTATION.

See integration project for a sample.

Parameters

All the parameters are named using the pattern reactiveAudit_<key>. To set the parameters, you can use:

  • environment variable (export reactiveAudit_logOutput=console)
  • java system properties (java -DreactiveAudit_file=low ...)
  • a properties file (reactiveAudit_file=low)

The values are read in the latter order.

The filename of parameters file is by default: reactiveAudit_properties To use another file, set the variable reactiveAudit:

$ java -DreactiveAudit=config.properties ...

or

$ export reactiveAudit=config.properties
$ java ...

You can set all the parameters described in <audit home>/etc/default.properties. For sample, to force the log to console without modify some file:

$ export reactiveAudit_logOutput=console
$ java ...

Contribute

We will be very happy if you can contribute. This king of tools must be tested with a lot of contexts. May be, the default parameters for different frameworks are not enough ; you have a better idea to integrate this tool with other ; Some rules can be extended to filter more precisely the context, ...

Get sources

$ git clone -b v0.7.1 --depth 1 --recursive https://github.com/octo-online/reactive-audit.git

Build

Target Command
Intellij $ ./gradlew idea
Eclipse $ ./gradlew eclipse
Compile $ ./gradlew usage
Distribution $ ./gradlew distZip
$ ./gradlew distTar
$ ./gradlew installDist

History

Version Comments
v0.8 Add @StartAudit annotation.
Add java.util.{Hashtable,Stack,Vector}
and java.util.concurrent.ConcurrentMap
Analyse the CPU to start the audit
v0.7.1 Fix bugs
v0.7 First public version
com.octo.reactive.audit

Versions

Version
0.8
0.7.1
0.7