lanwen / reactor-tools

A set of tools to improve Project Reactor's debugging and development experience.

Home Page:https://projectreactor.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Reactor tools (experimental)

Travis CI

⚠️ This project is in incubating phase and may or may not become a standalone project or a module of https://github.com/reactor/reactor-core in the future.

A set of tools to improve Project Reactor's debugging and development experience.

Getting it

Download it from Maven Central repositories (stable releases only) or repo.spring.io:

repositories {
  maven { url 'https://repo.spring.io/milestone' }
  // maven { url 'https://repo.spring.io/snapshot' }
}

dependencies {
  compile 'io.projectreactor:reactor-tools:$LATEST_RELEASE'
  // compile 'io.projectreactor:reactor-tools:$LATEST_SNAPSHOT'
}

Where:

$LATEST_RELEASE
$LATEST_SNAPSHOT

Usage

Reactor Debug agent - production-ready assembly back-tracing

ReactorDebugAgent is a Java agent which helps debugging exceptions in your application without paying a runtime cost (unlike Hooks.onOperatorDebug()).

It transforms (via bytecode transformation) chains like:

Flux.range(0, 5)
       .single()

to:

Flux flux = Flux.range(0, 5);
flux = Hooks.addCallSiteInfo(flux, "Flux.range\n foo.Bar.baz(Bar.java:21)"));
flux = flux.single();
flux = Hooks.addCallSiteInfo(flux, "Flux.single\n foo.Bar.baz(Bar.java:22)"));

making it possible to back trace the error:

java.lang.IndexOutOfBoundsException: Source emitted more than one item
  at reactor.core.publisher.MonoSingle$SingleSubscriber.onNext(MonoSingle.java:129)
   ...
  at java.lang.Thread.run(Thread.java:748)
  Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Assembly trace from producer [reactor.core.publisher.MonoSingle] :
  reactor.core.publisher.Flux.single(Flux.java:7380)
  foo.Bar.baz(Bar.java:22)
Error has been observed by the following operator(s):
  |_	Flux.single ⇢ foo.Bar.baz(Bar.java:22)

To enable it, you need to initialize the agent first:

ReactorDebugAgent.init();

ℹ️Since the implementation will instrument your classes when they are loaded, the best place to put it is before everything else in your main(String[]) methood:

public static void main(String[] args) {
    ReactorDebugAgent.init();
    SpringApplication.run(Application.class, args);
}

You may also re-process existing classes if you cannot run the init eagerly:

ReactorDebugAgent.init();
ReactorDebugAgent.processExistingClasses();

⚠️Be aware that the re-processing takes a couple of seconds due to the need to iterate over all loaded classes and apply the transformation.

Use it only if you see that some call-sites are not instrumented.

Limitations

Java 8 users must use JDK instead of JRE:
https://bytebuddy.net/javadoc/1.9.12/net/bytebuddy/agent/ByteBuddyAgent.html#install--

We plan to relax this requirement in future versions by shipping a "real" Java agent you can attach with the -javaagent: JVM flag.


Licensed under Apache Software License 2.0

Sponsored by Pivotal

About

A set of tools to improve Project Reactor's debugging and development experience.

https://projectreactor.io

License:Apache License 2.0


Languages

Language:Java 100.0%